Monday, April 4, 2016

Spring Boot with JSPs using Undertow

This is a follow-up to my previous post Spring Boot with JSPs in Executable Jars.

Undertow is another alternative for using an embedded container with Spring Boot. You can find general information in the Spring Boot reference guide chapter Use Undertow instead of Tomcat. While I was working on updating the Spring Boot documentation regarding the JSP support for Tomcat, I noticed the following line in the reference guide for Spring Boot 1.3.3:

"Undertow does not support JSPs."

Being a good citizen, I dug a little deeper and discovered the Undertow JSP sample application by Chris Grieger. It turns out that Undertow has indeed JSP support by using jastow, which is a Jasper fork for Undertow. The key was to adapt the Undertow JSP sample application for Spring Boot. Doing so was actually fairly straightforward. The actual Undertow configuration uses Spring Boot`s EmbeddedServletContainerCustomizer:


final UndertowDeploymentInfoCustomizer customizer = new UndertowDeploymentInfoCustomizer() {

  @Override
  public void customize(DeploymentInfo deploymentInfo) {
    deploymentInfo.setClassLoader(JspDemoApplication.class.getClassLoader())
    .setContextPath("/")
    .setDeploymentName("servletContext.war")
    .setResourceManager(new DefaultResourceLoader(JspDemoApplication.class))
    .addServlet(JspServletBuilder.createServlet("Default Jsp Servlet", "*.jsp"));

    final HashMap<String, TagLibraryInfo> tagLibraryInfo = TldLocator.createTldInfos();

    JspServletBuilder.setupDeployment(deploymentInfo, new HashMap<String, JspPropertyGroup>(), tagLibraryInfo, new HackInstanceManager());

  }
};

The full source is available in the JspDemoApplication class. The main issue is more or less the retrieval and configuration of the used Taglibraries. The Undertow JSP sample provides the TldLocator class, which does the heavy lifting. For our example, I am adapting that class so that it works in the context of Spring Boot. In Spring Boot we are dealing with über-Jars, meaning the resulting executable jar file will contain other jar files representing its dependencies.

Spring provides some nifty helpers to retrieve the needed Tag Library Descriptors (TLD) files. In TldLocator#createTldInfos I use a ResourcePatternResolver, specifically a PathMatchingResourcePatternResolver with a location pattern of classpath*:**/*.tld.


final URLClassLoader loader = (URLClassLoader) Thread.currentThread().getContextClassLoader();

final ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(loader);
final Resource[] resources;
final String locationPattern = "classpath*:**/*.tld";

try {
 resources = resolver.getResources(locationPattern);
}
catch (IOException e) {
 throw new IllegalStateException(String.format("Error while retrieving resources"
   + "for location pattern '%s'.", locationPattern, e));
}


Important

Don’t forget the asterix right after classpath. The classpath*: allows you to retrieve multiple class path resources with the same name. It will also retrieve resources across multiple jar files. This is an extremely useful feature. For more information please see the relevant JavaDocs for PathMatchingResourcePatternResolver.

Once we have the TLD resources, they will be parsed and ultimately used to create a collection of org.apache.jasper.deploy.TagLibraryInfo. With those at hand, we create a JSP deployment for Undertow using the DeploymentInfo and the TagLibraryInfo collection.


final HashMap<String, TagLibraryInfo> tagLibraryInfo = TldLocator.createTldInfos();
JspServletBuilder.setupDeployment(deploymentInfo, new HashMap<String, JspPropertyGroup>(), tagLibraryInfo, new HackInstanceManager());

And that’s it. Simply build and run the application and you should have a working JSP-based application.


$ mvn clean package
$ java -jar jsp-demo-undertow/target/jsp-demo-undertow-1.0.0-BUILD-SNAPSHOT.jar

In your console you should start seeing how the application starts up.



Once started, open your browser and go to the following Url http://localhost:8080/.


You can find the full source-code for this sample at https://github.com/ghillert/spring-boot-jsp-demo

Wednesday, March 9, 2016

Spring Boot with JSPs in Executable Jars


This part one of a multi-part series of blog posts on using JSPs with Spring Boot. Please find the second part here: Spring Boot with JSPs using Undertow.

Introduction

As you may know, I am a co-organizer for the DevNexus conference, the second-largest enterprise Java conference in North-America in Atlanta, GA. Together with Summers Pittman, I also maintain the Spring-based web-application that drives the website, schedule, call-for-paper (CFP) process and nowadays ticket registrations as well.


Goal

When we started planing for DevNexus 2016, I wanted to modernize the DevNexus application. Specifically, I planned to improve the underlying infrastructure of the app.
The goal was to move away from a stand-alone Tomcat-based servlet-container, which we had been using for the past couple of years. We endured several minutes of down-time whenever a new version of the app was deployed. Sometimes, the Tomcat instance or the server itself gave us grief. Furthermore, I longed for the ability to make blue/green deployments.
Therefore, the goal emerged to move the application over to a Platform as a Service (PaaS) offering, specifically Pivotal Web Services (PWS). I did not want to worry any longer about infrastructure issues, and blue/green deployments would be a breeze to accomplish using PWS.
In order to make this all happen, it became apparent, that migrating the application to Spring Boot would help in that endeavor. Luckily the application was generally architected in a way that made the migration to Spring Boot fairly straightforward. The migration also would simplify things greatly overall as we could take full advantage of Spring Boot’s defaults and also remove some duplicate functionality that was already baked into Spring Boot.
One main sticking point, though, was the used view technology. The DevNexus application has been using JavaServer Pages (JSP) for several years, and we accumulated a non-trivial amount of them. Ultimately, the plan is to migrate the user interface (UI) to a Single Page Application (SPA) but for the 2016 conference (February) that intent was unattainable due to time constraints.
Therefore, the whole migration was a bit in perils initially. As of the current version of Spring Boot at the time of this blog post 1.3.3, the reference guide states:
JSPs should be avoided if possible, there are several known limitations when using them with embedded servlet containers.
The reference guide then goes on to provide a list of JSP limitations in chapter 27.3.5. Specifically it states that:
An executable jar will not work because of a hard coded file pattern in Tomcat.
What a bummer…


Solution

Just to recap my requirement, I want to serve JSPs out of my classpath so that I can create executable Jar files. Basically, Eliminate the webapps folder.

Note

An interesting aspect of this is, that one can compose web applications out of multiple JARs, each possibly containing JSPs that are automatically served.
Unfortunately, taking my Maven-based project, putting your JSPs into e.g. src/main/resources/public or src/main/resources/static does not work. While reading the JSR-245 JavaServer™ Pages 2.1 Specification as well as the following in interesting blog post titled Serving Static Content with Servlet 3.0, it became apparent that I should also be able to store static resources in the META-INF/resources directory. Heureka it worked!
So the simple thing to remember is to store your JSPs in a folder like /src/main/resources/META-INF/resources/WEB-INF/jsp and you’re good to go (Plus some minor configuration around). To make things easy, lets go over a little example project.


Sample Project


Spring Initializr

The best way to start a Spring Boot project is to head over to http://start.spring.io/. Using Spring Initializr underneath, the website lets you customize and create Spring Boot starter projects. For our requirement, we want to create a simple web project.

Create starter project using spring initializr

Selecting web enables Full-stack web development with Tomcat and Spring MVC. Now you can press the Generate Project button, which will start the download of a Zip file containing your customized project.

Note

Instead of following the individual steps, you can also download the fully configured sample project from GitHub. Just clone the Demo Project using:


$ git clone https://github.com/ghillert/spring-boot-jsp-demo.git
$ cd spring-boot-jsp-demo


Unzip the project to a directory of your choosing.


Add Maven Dependencies

In order to enable JSP support we need to add a few dependencies to our new project in pom.xml.


<dependency>
 <groupId>org.apache.tomcat.embed</groupId>
 <artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
 <groupId>javax.servlet</groupId>
 <artifactId>jstl</artifactId>
</dependency>

Define the location of your JSP templates

Next we need to define the template prefix and suffix for our JSP files in application.properties. Thus add:


spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp




Important

Keep in mind that we will ultimatively, place the JSP templates under src/main/resources/META-INF/resources/WEB-INF/jsp/


Create a Spring Web Controller

Create a simple web controller:


package com.hillert.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloWorldController {

 @RequestMapping("/")
 public String helloWorld(Model model) {
  model.addAttribute("russian", "Добрый день");
  return "hello-world";
 }

}

Create the JSP Template

Next, create the corresponding JSP file hello-world.jsp in the directory src/main/resources/META-INF/resources/WEB-INF/jsp/:


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %><%
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
response.setHeader("Expires","0");

%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="form"   uri="http://www.springframework.org/tags/form" %>

<c:set var="ctx" value="${pageContext['request'].contextPath}"/>
<html>
 <body>
  <h1>Hello World - ${russian}</h1>
 </body>
</html>

Run the Sample Application

Now it is time to run the application - execute:

$ mvn clean package
$ java -jar target/jsp-demo-0.0.1-SNAPSHOT.jar


Conclusion

In this blog post I have shown how easy it is to use JSP templates with Spring Boot in executable Jars by simply putting your templates into src/main/resources/META-INF/resources/WEB-INF/jsp/.
While JSPs are often touted as being legacy, I see several reasons why they stay relevant today (2016):
  • You need to migrate an application to Spring Boot but have an existing sizable investment in JSP templates, that can’t be migrated immediately (My use-case)
  • While Single Page Applications (SPA) are all the rage, you may have use-cases where the traditional Spring Web MVC approach is still relevant
  • Even for SPA scenarios, you may still use dynamically-created wrapper pages (e.g. to inject data into the zero-payload HTML file)
  • Also JSP are battle-tested in large scale environments, e.g. at Ebay
  • Even with alternative frameworks, you may run into issues
In any event, I hope this expands your toolbox when using Spring Boot. There is simply no reason why you shouldn’t enjoy the benefits of Spring Boot to the fullest extent permissible by law. Remember, Make JAR, not WAR.

Friday, February 12, 2016

Starter Project - Angular 2.0 + TypeScript + WebPack + Bootstrap

As Angular 2.0 is finally in Beta (¡Yeah!), it is playtime now. In my opinion, the best starter project to use (Feb 2016 ;-) is Angular2 Webpack Starter by AngularClass. Unfortunately, it does not come with Bootstrap support out of the box. This is typically not a major issue but many front-end developers will be faced with 2 major changes:

  • Grunt, Gulp and Bower are dead, long live NPM and Webpack
  • TypeScript rules but how do I "require" my CSS dependencies?
Therefore, I created fork of the aforementioned starter project adding Bootstrap support. Also, in order to customize your Bootstrap theme, I believe it is advisable to use either Less or Sass. As I am more familiar with Less, I added it to my setup as well.



Monday, October 12, 2015

AngularJS + Karma - Loading JSON Files for Mocking HTTP Responses

In order to kick-off AngularJS projects, I have been looking at generator-gulp-angular lately, which you can find at:

https://github.com/Swiip/generator-gulp-angular

When doing your unit tests, it is quite convenient to mock HTTP responses using JSON files. However, having your unit tests load additional (JSON) files may not be super obvious using the Karma test runner.

bower.json

For the task at hand, I am using jasmine-jquery which provides “jQuery matchers and fixture loader for Jasmine framework”. Add that dependency to your bower.json file:


"devDependencies": {
  
  "jasmine-jquery": "2.1.1"
}


karma.conf.js

Now we need to do some additional configuration for Karma. By default, generator-gulp-angular wires the needed files up with:


return wiredep(wiredepOptions).js
  .concat([
    path.join(conf.paths.tmp, '/serve/app/index.module.js'),
    path.join(conf.paths.src, '/**/*.spec.js'),
    path.join(conf.paths.src, '/**/*.mock.js'),
    path.join(conf.paths.src, '/**/*.html'),
    {pattern: path.join(conf.paths.src, '../mocks/**/*.json'), watched: false, included: false, served: true}
  ]);



In order to make your JSON file available, add


{
  pattern: path.join(conf.paths.src, '../mocks/**/*.json'),
  watched: false,
  included: false,
  served: true
}



So that it becomes:


return wiredep(wiredepOptions).js
  .concat([
    path.join(conf.paths.tmp, '/serve/app/index.module.js'),
    path.join(conf.paths.src, '/**/*.spec.js'),
    path.join(conf.paths.src, '/**/*.mock.js'),
    path.join(conf.paths.src, '/**/*.html'),
    {pattern: path.join(conf.paths.src, '../mocks/**/*.json'), watched: false, included: false, served: true}]);


Mocks is a directory in my project’s root folder. Customize as needed. For further details see:

http://karma-runner.github.io/0.13/config/files.html

Now, you're ready for testing. In your spec aka unit test file, in the beforeEach:


beforeEach(inject(function (_$httpBackend_, _$rootScope_, $controller) {
…
}));


you can now mock up the $httpBackend:


jasmine.getJSONFixtures().fixturesPath='/base/mocks';

$httpBackend.whenGET('http://localhost:9876/api/plants').respond(
   getJSONFixture('plants.json')
);
$httpBackend.whenGET('app/components/plants/plants.html').respond('');
$httpBackend.flush();

Saturday, October 3, 2015

AngularJS Best Practices - Style Guide

Looks like the place du-jour for THE AngularJS style guide is here:

https://github.com/johnpapa/angular-styleguide

The author, John Papa, also provides the HotTowel Yeoman generator, that implements this style-guide:

https://github.com/johnpapa/generator-hottowel

If you're a TypeScript aficionado, you may want to keep an eye on the following GitHub issue:

https://github.com/johnpapa/generator-hottowel/issues/90

In the meantime - checkout:


And all this came up, as I was looking, for some good explanation for the advice to use AngularJS’
“Controller as” syntax and to avoid $scope as much as possible.

https://github.com/johnpapa/angular-styleguide#style-y030

A really good explanation is also here:

http://toddmotto.com/digging-into-angulars-controller-as-syntax/

Friday, October 2, 2015

TypeScript versus ES6


A good question is: Why would you want to use TypeScript versus ES6?

A few reasons for me:

  • I have to use a transpiler anyway in order to support older browsers such as Babel
  • TypeScript gives me types
  • You can still use JavaScript as valid TypeScript (TS being a superset of JS)
  • It seems to be a more natural fit for Java developers
  • Tooling support seems pretty good
  • AngularJS 2.0 will use it natively - as such you have Google and Microsoft supporting it

Resources

Will ES6 make Typescript irrelevant?
https://www.reddit.com/r/javascript/comments/31qocr/will_es6_make_typescript_irrelevant/

TypeScript vs ECMAScript 2015/2016
http://ilikekillnerds.com/2015/07/typescript-vs-ecmascript-20152016/

TypeScript and ES6 Dan Wahlin & Andrew Connell


Angular Air Episode 25: TypeScript or ES6 with Babel?


Thursday, October 1, 2015

AngularJS 1.x and TypeScript

I did a bit of research today on TypeScript. As it is favored (but not required) for the upcoming AngularJS 2.0 release, I wanted to dig a bit deeper. Keep in mind that as of Oct 2015, AngularJS 2.0 is still a pure alpha version and even new projects shall continue using AngularJS 1.4.

Nonetheless, it looks like TypeScript is a viable option even for the latest 1.4 version. In fact, Yeoman now provides an Angular starter (generator-gulp-angular) that gives you the option to use TypeScript as your language of choice.

Here are some resources that I thought were helpful:

http://www.developerhandbook.com/typescript/writing-angularjs-1-x-with-typescript/

I believe, that particularly for Java Developers, TypeScript could be quite interesting - as you have much better type-safety compared to using plain JavaScript. See the following blog entry by Veit Weber:

Why Java Developers might love TypeScript

There is a good presentation by Sander Mak from JavaOne: "TypeScript for Java Developers: Coding JavaScript Without the Pain" on that subject as well:


A longer version:



As you can have a much better OO experience with TypeScript, I think it will be also quite interesting to use rich domain objects with AngularJS rather than using JSON structures directly when retrieving data from your REST endpoints.

There is a great presentation by Gert Hengeveld from NG-NL 2015.



Slides: 

https://docs.google.com/presentation/d/1cbNH2WHO8WzF1XKPxMJ3gJXmfKnWAl3cN77eJJJdAEw/present?slide=id.p

Blog Post:

https://medium.com/opinionated-angularjs/angular-model-objects-with-javascript-classes-2e6a067c73bc

Convert JSON Structure to TypeScript Classes

If you create TypeScript classes that need to handle JSON, the follow online tool to generate TypeScript interfaces from JSON might be of interest:

http://json2ts.com/

TypeScript type definitions

I still need to wrap my head around TypeScript type definitions. They basically bolt on type definition for libraries that are not inherently based on TypeScript. There is a repository for them:

https://github.com/borisyankov/DefinitelyTyped


Monday, March 2, 2015

Still want to go to DevNexus 2015 (for free)? Room Volunteers Needed!

We are still looking for a few more room volunteers to help us with the monitoring and basic quality control of the breakout session rooms at DevNexus 2015 next week.

In total we need 24 volunteers (12 tracks x 2 days) for the 2 main conference days (March 11 and 12)  It will be first come, first serve - So please apply ASAP. We will be accepting room monitors from now and up until Thursday, March 5th.

The room monitor will be responsible for:

  • Getting a copy of the presentation slides from speakers right after each session
  • Making sure speakers don't go over their allotted time
  • Communication of any room related issues (power, sound , temp... etc).
  • Count the attendees in each session
  • Provide some feedback in regards to the observed sessions

A volunteer will be in charge of a single track room for one full day. Then s(he) will be free all day on the alternate conference day. For example, you monitor the Agile session room on Wednesday, then you are free to attend any session on Thursday.

Please contact info at ajug dot org if you are interested with the following info:

  • Day and Track
  • Alternative Day and Track 
  • Name
  • Email
  • Phone

Also, let us know if you have any further questions.

THANKS!

Saturday, January 10, 2015

DevNexus 2015 at BMW's Car Hackathon


Thanks to my colleague Sabby Anandan, DevNexus 2015 is getting some mentioning at BMW's Car Hackathon - Hack The Drive in San Francisco. The event takes place this weekend January 11-12.

Details at: http://hackthedrive.com/

Here are some photos:




Thursday, January 8, 2015

DevNexus 2015 - Early Bird pricing ends Jan 9

The countdown for DEVNEXUS 2015 (Workshop day March 10, main conference March 11-12) is on! The AJUG team has been working hard to secure speakers, build the new event site and make this year's event the best one ever:

  • 3 days (1 workshop day and 2 conference days) 
  • 12 tracks 
  • 120 sessions 
  • expected attendance of 1500 

You can see the accepted list of speakers and sessions at http://www.devnexus.com/.

Please note that the Early Bird pricing ends this Friday Jan 9th!! So if you want to take advantage of the super low event price of $250 (other developer conferences of this scale cost $1000-$1800 to attend) then register this week.

Also don’t forget that we have a whole day of workshops on March 10th. This conference has sold out every year for the last 6 years so be sure to register now at:


A big THANK YOU to all of our sponsors that help make this event possible:

PLATINUM SPONSOR


GOLD SPONSORS


MEDIA PARTNER


SILVER SPONSOSRS


COCKTAIL HOUR SPONSOR


See you all in March!!!