Spring boot and CORS

A while back I wrote a post Building a REST service with Spring and today I needed to try out the CORS support to allow a similar Spring based REST service to allow for CORS access from a React application I’m working on.

It’s super easy to allow access to all clients by simply adding @CrossOrigin to your controller, for example

package demo;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@CrossOrigin
@RestController
public class SampleController {

    @RequestMapping("/purchaseOrder")
    public PurchaseOrderType getPurchaseOrder() {
        return new PurchaseOrderType(1234);
    }
}

Equally we can just add the same annotation to REST methods instead of the whole controller, for example

@CrossOrigin
@RequestMapping("/purchaseOrder")
public PurchaseOrderType getPurchaseOrder() {
   return new PurchaseOrderType(1234);
}

Note: @CrossOrigin is the equivalent of @CrossOrigin(origins = “*”).

If we want to limit the origins then we simply use the following instead

@CrossOrigin(origins = "http://localhost:3000")

// or an array of origins like this

@CrossOrigin(origins = {"http://localhost:3000", "http://localhost:3001"})

ANTLR in C#

In the previous post Starting out with ANTLR we look at the basics of creating a grammar and generating code from it, now let’s take that very simple grammar and integrate it into a C# application.

Here’s the grammar again (from our grammar file queryLanguage.g4)

Note: We’re going to capitalize the grammar name as this will then by more in the style of C# class names.

grammar QueryLanguage;

query
    : expression
    ;

expression
    : STRING
    | NUMBER
    | expression 'AND' expression
    | expression 'OR' expression
    ;

WS  : (' '|'\t'|'\r'|'\n')+ -> skip;

STRING : '"' .*? '"';
SIGN
   : ('+' | '-')
   ;
NUMBER  
    : SIGN? ( [0-9]* '.' )? [0-9]+;

The ANTLR4 JAR is not compatible with the ANTRL4 Nuget package, so instead for our Example application we’ll use an alternative, the Antlr4 CodeGenerator, so follow these steps to create an application

  • Create a .NET Core Console application
  • Editor the SDK project file and change netcoreapp3.1 to net472
  • Add the ANTLR4.Runtime and Antlr4.CodeGenerator Nuget packages
  • Add your QueryLanguage.g4 grammar to the project

If you select the .g4 file you can now view the properties for that file within Visual Studio 2019 and (if you wish to) change what’s generated by ANTLR. Let’s just ensure Generate Visitor is Yes.

For some reason a .NET framework 4.7.2 project does not include the properties and whilst we can edit the .csproj file to get things working, I’ve found the above steps the simplest to get ANTLR running in a .NET application at the time of writing.

I’ve found I do still need to edit the .csproj file to add the following

<ItemGroup>
  <Antlr4 Update="QueryLanguage.g4">
    <Listener>false</Listener>
    <CustomToolNamespace>Example.Generated</CustomToolNamespace>
  </Antlr4>
</ItemGroup>

<PropertyGroup>
  <Antlr4UseCSharpGenerator>True</Antlr4UseCSharpGenerator>
</PropertyGroup>

Change Example.Generated to the preferred namespace for the generated files.

Now build the project and if all goes well there should be no errors and the ANTLR code should be generated in obj/Debug/net472 (or whatever configuration you’re using).

Let’s now make some changes to our grammar to make writing Visitor code simpler by adding labels to our expression code, the changes are listed below

expression
    : STRING #String
    | NUMBER #Number
    | expression 'AND' expression #And
    | expression 'OR' expression  #Or
    ;

We use # to create a label and this will turn into a Visit function with the label, i.e. VisitAnd, VisitoOr etc.

All we’re going to do with this grammar is use the Visitor pattern/class to generate code where strings are all lowercase, AND becomes & and OR becomes |, ofcourse you could produce byte code or do all sorts of things with your input.

Create a new file name QueryLanguageVisitor.cs and it should look like this

using Example.Generated;

namespace Example
{
  public class QueryLanguageVisitor : QueryLanguageBaseVisitor<string>
  {
    public override string VisitString(QueryLanguageParser.StringContext context)
    {
      return context.GetText().ToLower();
    }

    public override string VisitNumber(QueryLanguageParser.NumberContext context)
    {
      return context.GetText();
    }

    public override string VisitAnd(QueryLanguageParser.AndContext context)
    {
      return Visit(context.expression(0)) + "&" + Visit(context.expression(1));
    }

    public override string VisitOr(QueryLanguageParser.OrContext context)
    {
      return Visit(context.expression(0)) + "|" + Visit(context.expression(1));
    }
  }
}

As you can see from the above code, we subclass QueryLanguageBaseVisitor (a generated file) and the generic parameter is set as a string as our result of running through the QueryLanguageVisitor will simply be another string.

In the case of the AND and OR which ofcourse are binary expressions, i.e. require two parameters either side of the AND or OR and these may themselves be expression, hence we call Visit those expressions.

At this point, we have nothing to actually run the QueryLanguageVisitor so in the Main method place the following code

// add these using clauses
// using Antlr4.Runtime;
// using Example.Generated;

// example expression
var expression = "\"HELLO\" AND 123";

var inputStream = new AntlrInputStream(expression);
var lexer = new QueryLanguageLexer(inputStream);
var tokenStream = new CommonTokenStream(lexer);
var parser = new QueryLanguageParser(tokenStream);

var visitor = new QueryLanguageVisitor();
var query = parser.query();
var result = visitor.Visit(query);

In the code above, we create an ANTLR input stream (you can ofcource use an AntlrFileStream if you’re taking input from a file). Next we use our generated lexer which is passed into the CommonTokenStream and this in turn is passed into our generated QueryLanguageParser.

Finally we create our newly added QueryLanguageVisitor which will have functions based upon our grammar, in our case the startRule is query hence we call this method and pass the result into the Visit method of our QueryLanguageVisitor. The result (assuming no errors) will be

"hello" & 123

A more fully featured (i.e. includes error handling) implementation would be as follows (concepts and code snippets taken from various existing samples)

public class ParserResult
{
  public bool IsValid { get; internal set; }
  public int ErrorPosition { get; internal set; } = -1;
  public string ErrorMessage { get; internal set; }
  public string Result { get; internal set; }
}

public static class Query
{
  public static ParserResult Parse(string expression, bool secondRun = false)
  {
    if (String.IsNullOrWhiteSpace(expression))
    {
      return new ParserResult
      {
        IsValid = true,
        Result = null
      };
    }

    var inputStream = new AntlrInputStream(expression);
    var lexer = new QueryLanguageLexer(inputStream);
    var tokenStream = new CommonTokenStream(lexer);
    var parser = new QueryLanguageParser(tokenStream);

    lexer.RemoveErrorListeners();
    parser.RemoveErrorListeners();
    var customErrorListener = new QueryLanguageErrorListener();
    parser.AddErrorListener(customErrorListener);
    var visitor = new QueryLanguageVisitor();

    var queryExpression = parser.query();
    var result = visitor.Visit(queryExpression);
    var isValid = customErrorListener.IsValid;
    var errorLocation = customErrorListener.ErrorLocation;
    var errorMessage = customErrorListener.ErrorMessage;
    if (result != null)
    {
      isValid = false;
    }

    if (!isValid && !secondRun)
    {
      var cleanedFormula = string.Empty;
      var tokenList = tokenStream.GetTokens().ToList();
      for (var i = 0; i < tokenList.Count - 1; i++)
      {
        cleanedFormula += tokenList[i].Text;
      }
      var originalErrorLocation = errorLocation;
      var retriedResult = Parse(cleanedFormula, true);
      if (!retriedResult.IsValid)
      {
        retriedResult.ErrorPosition = originalErrorLocation;
        retriedResult.ErrorMessage = errorMessage;
      }
      return retriedResult;
    }
    return new ParserResult
    {
      IsValid = isValid,
      Result = isValid || result != null 
        ? result
        : null,
      ErrorPosition = errorLocation,
      ErrorMessage = isValid ? null : errorMessage
    };
  }
}

public class QueryLanguageErrorListener : BaseErrorListener
{
  public bool IsValid { get; private set; } = true;
  public int ErrorLocation { get; private set; } = -1;
  public string ErrorMessage { get; private set; }

  public override void ReportAmbiguity(
    Parser recognizer, DFA dfa, 
    int startIndex, int stopIndex, 
    bool exact, BitSet ambigAlts, 
    ATNConfigSet configs)
  {
    IsValid = false;
  }

  public override void ReportAttemptingFullContext(
    Parser recognizer, DFA dfa, 
    int startIndex, int stopIndex, 
    BitSet conflictingAlts, SimulatorState conflictState)
  {
    IsValid = false;
  }

  public override void ReportContextSensitivity(
    Parser recognizer, DFA dfa, 
    int startIndex, int stopIndex, 
    int prediction, SimulatorState acceptState)
  {
    IsValid = false;
  }

  public override void SyntaxError(
    IRecognizer recognizer, IToken offendingSymbol, 
    int line, int charPositionInLine, 
   string msg, RecognitionException e)
 {
   IsValid = false;
   ErrorLocation = ErrorLocation == -1 ? charPositionInLine : ErrorLocation;
   ErrorMessage = msg;
 }
}

Now the code that uses our parser simply looks like this (and includes error handling)

var expression = "\"HELLO\" AND 123";
var result = Query.Parse(expression);

Starting out with ANTLR

ANTLR (ANother Tool for Language Recognition) is a parser generator.

You might be designing your own programming/scripting language or defining something a little simpler, such as query language for your application or even just something to parse user input (which is not necessarily simpler).

ANTLR can be downloaded from here and whilst the tool itself is written in Java it can generate parser code in Java, C#, Python, JavaScript and more.

Note: I’ve downloaded the “Complete ANTLR 4.8 Java binaries jar” hence the commands listed will all be in relation to that JAR.

Grammar files

Before we can do anything meaningful with ANTLR we need to define a grammar for our lexer and parser to be generated from. These are text files with the extension .g or .g4 (for ANTLR 4 compatible grammars) and looks lot like BNF. Let’s create a grammar for a very simple query language that we’d like to incorporate into an application.

We start by creating a file named querylanguage.g4

I’m using Visual Studio Code to write the grammar and using the excellent ANTLR4 grammar syntax support extension to aid in developing the grammar.

The first thing we add to the grammar is

grammar querylanguage;

The grammar name must match the name of your grammar file. It can be prefixed with lexer or parser if you want to write grammar specific to either a lexer or parser, without these we’re creating a combined lexer and parser grammar.

Here’s all the options for the grammar keyword.

lexer grammar querylanguage;

// or

parser grammar querylanguage;

// or 

grammar querylanguage;

Before we extend our grammar let’s talk about comments – single line comments can be created using // and multi line using /* */.

We create our grammar using a combination of rules and tokens. Rules should be declared using camelCase whereas tokens should be all upper case. We’ll need an entry point (or start rule) so let’s extend our grammar within a start rule named query and this will be made up of an expression rule. We’ll also add a token to handle string types.

grammar querylanguage;

query
    : expression
    ;

expression
    : STRING
    | NUMBER
    ;

STRING : '"' .*? '"';
SIGN
   : ('+' | '-')
   ;
NUMBER  
    : SIGN? ( [0-9]* '.' )? [0-9]+;

We’ll look at the syntax of our rules etc. in a moment.

As you can see, a rule is made up of a name followed by a colon and then either another rule or token and finally a rule or token is terminated with a ;. Alternate rules or tokens are defined using the | operator. So in the example above we have two token rules, query and expression and three tokens rules, STRING, SIGN and NUMBER.

If we input “Hello World” then the ANTLR tokenize and parse this as a STRING. If we input 1234 then we’ll see this tokenize and parsed as a NUMBER. We can now start to build up our grammar from these basic building blocks, so let’s add some logic operators, AND and OR. We’ll also add a token rule to deal with whitespace characters (which we want to ignore). So change/add the following to the existing grammar

expression
    : STRING
    | NUMBER
    | expression 'AND' expression
    | expression 'OR' expression
    ;

WS  : (' '|'\t'|'\r'|'\n')+ -> skip;

WS is a special token rule which basically skips/ignores the various whitespace characters.

Let’s now take a look at the rule syntax we’ve used.

  • ‘ ‘ – we denote literals within single quotes, so our previous declaration of a STRING show that a string starts with a string literal double quote and ends with the same.
  • | – this is used to give alternate options, so the WS token rule is a ‘ ‘ OR ‘\t’ OR…
  • (…) – this brackets acts as a subrule or grouping, so in this case of the WS token rule, we’re simply creating a group of white space characters following by a +, hence the + acts upon the group of characters
  • + – the + sign means 1 or more, hence for the WS token rule we’re saying the WS is 1 or more of any of the supplied literal characters.
  • -> – this means rewrite this rule, in the case of WS this basically rewrites the rules to skip (which simply means ignore WS characters
  • . – the dot is a wildcard, so in the STRING example we’re simply saying match any character
  • * – this means zero or more, in the STRING example when applied to the ., i.e. .* we’re saying a string is 0 or more of any character
  • ? – means optional, an example is the use of SIGN? which simply means a SIGN is optional
  • […] – square brackets denote a character set, for example [0-9] means characters 0 through to 9 inclusive

See Grammars for the rest of the Grammar syntax.

Another interesting keyword is fragment, for example

HexLiteral : '0' ('x'|'X') HexDigit+ ;
fragment HexDigit : ('0'..'9'|'a'..'f'|'A'..'F') ;

A fragment is a modifier which doesn’t result in a token being visible to the parser but is more like an inline rule, in that it’s used “inline” within other rules, what if gives us is a way to create more reusable constructs and is useful if we want to share rules amongst other rules or to just make rules more readable.

Reserved keywords

ANTLR4 includes the following reserved words


import, fragment, lexer, parser, grammar, returns,
locals, throws, catch, finally, mode, options, tokens

So obviously you cannot use these for your own rule names.

Debugging our grammar with the VS Code, ANTLR4 grammar syntax support extension

This extension is really useful when working with our grammars. First off we have syntax highlight and auto completion, which is always useful but it also includes a debugger and can display ANTLR exceptions when we’re not matching tokens or rules.

To debug your grammar in VS Code, either editor your launch.json or add a configuration via Run | Add Configuration, here’s the configuration for testing our grammar

"version": "0.2.0",
"configurations": [
  {
    "name": "Debug ANTLR4 grammar",
    "type": "antlr-debug",
    "request": "launch",
    "input": "sample.txt",
    "grammar": "querylanguage.g4",
    "startRule": "query",
    "printParseTree": true,
    "visualParseTree": true
  }
]

You’re might want to change the “input” file to a named file of your choice, but basically this is just a text file where we put our test to be parsed via the grammar, so for example my sample.text file looks like this

"HELLO" AND 123

The “startRule” is the top level rule we want to parse our input through, so in our example it’s the query rule. Ofcourse we also need to tell the antrl-debug the “grammar” to use.

Now in VS code press the run button using this configuration and you’ll get to see the output of the parse tree, for example

Parse Tree:
query (
 expression (
  expression (
   ""HELLO""
  )
  "AND"
  expression (
   "123"
  )
 )
)

There’s also a lovely parse tree so you can see how your grammar was parsed and which rules matched to which input.

Generating code

Everything we’ve looked at is great, but ofcourse we’ll want to actually include our grammar within our application and ANTLR comes to help by allowing us to use the previously downloaded JAR to generate the code for our preferred (and ofcourse supported) language.

By default if you run

java -jar antlr-4.8-complete.jar .\querylanguage.g4

Then you’ll get a set of files produced which include Java source files for a Lexer, Parser and Listener. If you want to generate a Visitor then add the -visitor switch, like this

java -jar antlr-4.8-complete.jar -visitor .\querylanguage.g4  

As I’m wanting to generate C# source files, we can simply add the -Dlanguage switch, for example

java -jar antlr-4.8-complete.jar -visitor -Dlanguage=CSharp .\querylanguage.g4

But sadly this doesn’t work. It seems that whilst the JAR supports generating C# code the ANTLR .NET package is not compatible. In another post we’ll look at how we can generate C# code from our grammar.

References

ANTLR Tool Command Line Options
ANTLR 4 Documentation
vscode-antlr4
Sample grammars
Grammars
Cheat Sheet
Lexer Rules

Powershell from File Explorer’s context menu

Let’s add an “Open Poweshell” option to the File Explorer context menu.

  • Run Regedit
  • Go to HKEY_CLASSES_ROOT\Directory\shell
  • Add a new key to this, we’ll call ours power_shell as you may already see a PowerShell option and I don’t want to change that one
  • Change Default for the key to the text you want display in your context menu, i.e. Open Powershell Here
  • Add a new string value named Icon and in it’s value put C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe
  • Add a new key to the power_shell key, named command. This is what’s actually run in the Default key put C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -NoExit -Command Set-Location -LiteralPath ‘%L’

This will now show the Open Powershell Here option when you click on a folder in File Explorer, but what about if you’re already in the folder and want to open powershell from the current folder, then…

  • If you’ve closed Regedit then run Regedit again
  • Go to HKEY_CLASSES_ROOT\Directory\background\shell
  • Add a key named power_shell as before
  • As before we now add a string value named Icon with the same value as above
  • Again add a command subkey and with a slightly change add the following value into the Default key C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -NoExit -Command Set-Location -LiteralPath ‘%V’ – note we change %L to %V

Building and testing TypeScript code using Github actions

In previous posts we’ve used Github actions to build .NET core code, now let’s create a workflow to build/transpile a TypeScript application.

  • Create a file (mine’s named build.yml) in your Github repo. in the folder .github/workflows
  • As per other examples of such a .yml action file we need to give the build a name and set up the triggers, so let’s do that, here’s the code
    name: Build
    
    on:
      push:
        branches: [ master ]
      pull_request:
        branches: [ master ]
    
    jobs:
      build:
    
        runs-on: ubuntu-latest
    

    In the above we’ve simply named the action Build which is triggered by pushes to master (and pull requests). We then set the action up to run on an ubuntu VM

  • Next we’ll add the following code to create a strategy (basically think, job configurations and application wide variables)
    strategy:
      matrix:
        node-version: [12.x]
    

    In this case we’re creating a variable named node-version with the version of node we want to use.

  • Now we’ll create the steps for the build
    steps:
      - uses: actions/checkout@v2
      - name: Node.js
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm install -g yarn    
      - name: yarn install, build and test
        run: | 
          yarn 
          yarn build
          yarn test
    

    Firstly we declare the checkout action to be used, then we used the setup-node action to (as the name suggests) setup node with the version we defined. In this example we then run npm to install yarn. Obviously we could have simply used npm instead (and you can replace the yarn commands with npm if you wish).

    Finally we have a step to install, build and test our code running the relevant yarn commands to carry out these tasks.

The above expects the package.json of your project to have scripts named test and build. For example

"scripts": {
  "test": "jest",
  "build": "tsc"
}

TIB/Rendezvous Daemon viewer

A useful tool for checking whether a user/machine is connected to TIBCO RV is to connect to their daemon. The TIBCO RV daemon includes a web browser – simply connect to the following

http://hostname:7580/index.html

Setting the host name to that of the machine you want to inspect (or their ip address).

This will display general information about the installed version of rvd if it’s installed ofcourse. Selecting the Client option will show the daemon’s client connections. For each connection is an Identifier which you can click on to see more details regarding that connection. From this you can also view the Subscriptions, i.e. what topics you’re daemon is listening on.

The Service option will show what service the daemon is connected to as well as all the other hosts that are connected.

Finally there’s the Current Log showing the log from the daemon.

Resizing a component relative to it’s parent (position: fixed)

In the previous post I mentioned how we can fix a footer to the bottom of the viewport, but we have an issue where the width extends outside the width of the parent.

NOTE: This post discusses a partial solution to this issue. In that, if the browser window size changes this works, but if your viewport size changes, it doesn’t. So for example if you have a flyout Drawer component or the likes which takes up space on the page, then no window resize takes place, only a layout change takes place. If I resolve this I’ll update this post.

To solve this we’re going to create a ref on our parent div and monitor it’s size changes and then apply them to our footer.

So assuming we’re using material-ui’s createStyle, with the following CSS (or use plain CSS or your preferred CSS library)

footer: {
  position: "fixed",
  bottom: 0,
  marginBottom: "10px",
  textAlign: "left",
},

Here’s an abridged version of my code (using a React functional component)

const targetRef: any = useRef(null);
const [relativeWidth, setRelativeWidth] = useState(0);

useLayoutEffect(() => {
  function updateWidth() {
    if (targetRef != null && targetRef.current != null) {
      setRelativeWidth(targetRef.current.offsetWidth);
    }
  }

  window.addEventListener("resize", updateWidth);
  updateSize();
  return () => window.removeEventListener("resize", updateWidth);
}, []);

return (
  <div ref={targetRef}>
    {/* our other elements */}
    <div className={classes.footer}
      style={{ width: relativeWidth }}>
      {/* our footer elements */}
    </div>
  </div>
);

So what we’re doing is getting a ref to the parent div and storing the relativeWidth in the component’s state using useState (which we set up at the start of the function). Using useEffect, we create a listener to the window’s resize events and then update our state. Finally in the footer style we set the width explicitly using then relativeWidth that we stored.

Not only will this now display correctly relative to the parent div, but also resize relative to it as well.

These are early days for this code, but so far this looks to work a treat.

How to create a footer using CSS

To create a footer, a div that sits at the bottom of your viewport, using the position: “fixed” CSS.

For example here’s a snippet using material-ui’s createStyles function

footer: {
  position: "fixed",
  bottom: 0,
  marginBottom: "10px",
},

This will display the element it’s assigned to at the bottom of the screen using the fixed and bottom attributes, just to give it a bit of space we’ll using marginBottom so it floats above the bottom of the screen.

There’s a problem with the fixed position. It’s width is relative to the viewport, not relative to the parent.

This mean’s in a situation where you might have a user interface where the screen is divided into two columns and you want the fixed div in the right most column, you’ll find the width will extend outside if the view.

We’ll look at how to solve this, in the next post.

Accessing the host machine via the Android emulator

If you want to access a service/server running on the host machine you need to use specially designated IP addresses, such as 10.0.2.2.

Note: The following table is taken from Network address space

Network AddressDescription
10.0.2.1Router/gateway address
10.0.2.2Alias to your host loopback (i.e. 127.0.0.1 on the host machine)
10.0.2.3First DNS server
10.0.2.4/10.0.2.5/10.0.2.6Optional, second, third and fourth DNS server (if any)
10.0.2.15The emulated device network/ethernet interface
127.0.0.1The emulated device loopback interface

Blazor and the JavaScript interop.

In the post Logging in Blazor we saw how we can use the IJSRuntime to call out to the JavaScript runtime.

Ofcourse we can interop with any JavaScript code within our application, so for example let’s make some simple changes to the index.html from that post and add a script block, such as this

<script>
   function displayMessage(msg) {
      alert(msg);
   }
</script>

Nothing very special here, but we just want something visual to more easily see our interop calls.

Next, in our .razor file let’s simple add a button and associated code block

<button @onclick="DisplayMessage">Alert</button>

@code {
   private void DisplayMessage()
   {
      JsRuntime.InvokeVoidAsync("displayMessage", "Hello JavaScript World");
   }
}

The IJSRuntime interface has the following methods

public interface IJSRuntime
{
   ValueTask<TValue> InvokeAsync<TValue>(string identifier, 
      object[] args);
   ValueTask<TValue> InvokeAsync<TValue>(string identifier, 
      CancellationToken cancellationToken, object[] args);
}

As you can see, both return a ValueTask, hence are awaitable, but neither matches our InvokeVoidAsync method. This is because there are a bunch of extension methods within JSRuntimeExtensions. These extension methods check that the supplied IJSRuntime is not null and then calls the interface methods.

In the example above, we are not interested in the return value, so let’s now return some value from our JavaScript…

Change the script to

<script>
   function displayMessage(msg) {
      return prompt(msg);
   }
</script>

and now change the C# code in our code block to

private async void DisplayMessage()
{
   Debug.WriteLine(
      await JsRuntime.InvokeAsync<string>(
         "displayMessage", "Hello JavaScript World"
      )
   );
}

At this point, we’re receiving the return from our JavaScript function and (in the case of a WebAssembly application) outputting to the browser console.

Ofcourse we can now write JavaScript code and call this from Blazor as well.