Extending Selenium with page objects

As all who have used it know Selenium is a powerful tool when testing front-end applications. I personally use it in combination with protractor. This is because most of the work I do is with Angular and AngularJS applications.

When you are using Typescript extending classes is an easy thing. In light of this I’ve been experimenting with new approaches to creating page objects. Continue reading

Angular2 and Spring Boot: Getting Started

Combining Angular2 and Spring Boot is a great way of getting up and running quickly with a new web application. However, it can be challenging to fit all the different pieces together in the beginning. In this blog post we will create a new project that is easy to build and run across different environments. The goal is to create a minimal, but runnable, application with as little dependencies and setup as possible. You can then start expanding the application however you see fit.

We will create the Angular2 application using angular-cli. This allows us to easily generate a new project with a clear structure. This will also make it easy to add new elements to our Angular2 application. When adding new elements with angular-cli, we will maintain the same structure and wire the new elements together automatically. Angular-cli is an npm module, so it requires Node and npm to install and run. Make sure to install a recent version of both of these applications before continuing with the steps below. We will use Maven as the overall build manager for our application.

The steps should be easy to follow and will not require a lot of work. However, you can get the result directly in this GitHub repository if you want to. There is a seperate commit for every step.

Step 1: Generate a new Spring Boot project

The first step is to generate a new Spring Boot project at https://start.spring.io. I’ve used the values in the screenshot below. Of course you can use your own group and artifact ids. We need at least the Web plugin to let Spring Boot serve the Angular2 application. If you already know you need more dependencies for your project, feel free to add them.

Click on Generate Project to download the zip file with your new Spring Boot project. Extract the zip file somewhere on your computer. Then open a command prompt and go to the newly created project directory.

Step 2: Split the project into seperate modules

We will want to use seperate Maven modules for the frontend and backend. Let’s start by creating the correct directory structure and copying the pom file.

Edit pom.xml in the top level project directory and make it look like this:

Next, edit pom.xml in the backend directory and make it look like this:

Finally, copy the pom.xml from the backend directory to the frontend directory and edit it to look like this:

Step 3: Add the Angular2 application to the project

If angular-cli is not installed on your system already, use npm to install it now.

To keep the blog post readable, I’m not showing the output of the command. You can ignore any warnings about optional dependencies. The -g flag tells npm to install it globally. This means you can run the command ng from the command line anywhere on your computer. Let’s use angular-cli to generate our Angular2 application in the frontend\src\main\frontend directory.

We just told angular-cli to generate a new project. We let it skip creating a git repository, because we are not in the top level directory of our project. We specified that the output directory should be frontend and called the new application ng2boot. We chose src\main\frontend to prevent maven from putting the source files, including the node_modules directory, in our jar.

Step 4: Configure Maven to build the Angular2 application

We will use the frontend-maven-plugin to build the Angular 2 application with Maven. First, let’s add the plugin to the fronted pom in the build/plugins section.

We specify the node and npm versions and the working directory in the configuration section. We also add three executions. The first execution downloads and installs node and npm to the directories node and node_modules. Npm will download a lot of packages, so add both directories to the ignore list of your version control system. The second execution runs npm install in the working directory to download all npm dependencies of our project. The third execution runs npm run build in the working directory to build the Angular2 application.

By default, angular-cli will write the final Angular2 application in the src\main\frontend\dist directory. We can adhere to the Maven standard directory layout better by configuring angular-cli to write it to the target directory. This will also delete the built application, along with all other build artifacts, when we run mvn clean. Edit .angular-cli.json and change the outDir in the apps section.

Step 5: Let Spring Boot serve the Angular2 application

Maven will now build (and clean) the Angular2 application, but it will not end up in our final jar. Spring Boot will serve static content from a number of directories on the Java classpath. So we have to make sure that the Angular2 application ends up in one of those directories. Files on the classpath that are not Java classes, are known as resources. Maven copies all resources (normally found in src\main\resources) into the final jar. Add the packaged Angular2 application to the resources by adding the snippet below to the build section in pom.xml. The given targetPath will put it in /static on the classpath and Spring Boot will serve it from there.

Because the Spring Boot backend is in another module, we will need to add a dependency to the Angular2 application. Edit the backend pom file and add the following to the list of dependencies.

Step 6: Fire it up!

We are now ready to build and run our application. From the top level directory of our project, run:

Wait for the application to start and then point your browser to http://localhost:8080

Angular2 application served by Spring Boot

If you have configured everything properly, your application should look just like the above image. If it doesn’t, have a look at the GitHub repository which has the finished application in it. And of course, don’t hesitate to leave a reply if you’re having trouble getting the application to build or start.

Step 7: Using the angular-cli development server with your Spring Boot backend

One of many nice features of angular-cli is the development server. It will serve the Angular2 application, just like Spring Boot. However, every time we save a source file, it will automatically rebuild the application and refresh the browser.

There is one problem though. Maven (running our backend) and the development server (running our frontend) are seperate processes listening on seperate ports. This prevents Angular2 from making backend requests because it violates the Same Origin Policy of our web browser. Web browsers only allow backend requests to the same origin that the web application making the requests was downloaded from.

Thankfully, we can let angular-cli act as a proxy for our Spring Boot backend. The Angular2 application will send backend requests to thedevelopment server, which will forward them to Spring Boot. Now, the Angular2 application can make backend requests to the same origin it came from.

Edit package.json and change the start script to add the proxy configuration.

The start script now references proxy.conf.json. Create that file, with the following content:

This configuration assumes all backend requests will be made to (sub paths of) /api. You can of course choose any url you like. Now, when you run npm start in the frontend\src\main\frontend directory, the development server will run your Angular2 application. It can be reached at http://localhost:4200. Don’t forget you have to start your backend seperately. You can do this by running mvn spring-boot:run in the backend directory.

I hope you enjoyed this blog post. If you found it useful, or if you have any questions, please let me know by leaving a reply. Happy coding!

Integrate Angular in Spring Boot with Gradle

Having a Angular HTML5 single page application and a Spring Boot application, we would like to serve the complete Angular app from Spring Boot. This blog shows you a couple simple steps to get everything up and running: run NPM from Gradle, integrate the Gradle frontend build in the main build and support HTML5 mode in the ResourceHandler of Spring Boot.

Run NPM from Gradle

Create a subdirectory called frontend with the frontend code and build scripts (webpack, npm). Let’s assume our npm start and npm run watch output to the /frontend/dist/ directory.

First we need to make sure the frontend code is build when we run gradle build on our project. We can use the plugin gradle-node-plugin for this. Go ahead and create a /frontend/build.gradle file.

Now, if we run a gradle build from our frontend subdirectory:

  • node will be downloaded
  • npm install will be executed
  • npm run build will be executed

Run integrated Gradle build

To run the frontend submodule integrated from our root project, all we need to do is include a settings.gradle at the root of the project.

Go ahead and run gradle build from the root of our project and see that npm is downloaded and the expected npm tasks are run.

We need to include the distribution of the frontend build in the JAR. Thus the frontend:build task needs to be run before we process the resources of the JAR. Go ahead and add the following snippet to /build.gradle.

Support Angular HTML5 mode

Now all we need to do is create support for HTML5 mode in Angular. Angular is a single page application and subroutes of the application are default served with a ‘#’ hashtag separator. If we want to have regular paths, we can enable HTML5 mode. The problem in serving this Angular HTML5 application from Spring Boot is that the Spring Boot ResourceHandler cannot find these resources, since the real resources is the index.html with the JavaScript files. With the next code snippet we instruct Spring Boot to look for the index.html as well. This is inspired by http://stackoverflow.com/questions/24837715/spring-boot-with-angularjs-html5mode

Happy coding!