Review Java EE6 and JavaFX 1.3 - Part I, the back-end

Mark Bakker

Summary

In the first part of this review (the JavaEE6 back-end) I tested a small application which is a JSON REST service to be used as back-end for a JavaFX front-end. My conclusion for now is that JavaEE6 has a lot of new features which makes it a lot easier to use Java EE without extra libraries like Spring, Seam or Resteasy. I was able to make a back-end application which was noticeable fast with a low overhead in bandwidth and CPU usage.

Introduction

In a search for the current best technology platform I am building a small real-world application for personal use in different languages and frameworks. First up is Java EE 6 and JavaFX 1.3.

I think this review can be helpful for others as well. If you just want to see the implementation you can skip the functional and technical requirements. If you are interested in the application and want to help creating the new version; please send me a reply:-).

Functional requirements

Currently I am using an application for managing my personal finances. This application is created in Java Swing with a Hsql database beneath it. The application functions well, but is only usable for one person at a time an the Hsql database is not ideal.

I created this application because I could not find any other application to manage my personal finances which has the following features (and more):

  • Register coming transactions on budgets
    • One time transactions
    • Repeated transactions (currently with a cron syntax)
  • Be able to report on self defined periods
    • The period can be defined by a start date and and Unix cron syntax
    • The period reports shows
      • The budget for that period (based on all coming transactions) for each budget entry
      • The total amount spent for that period
      • The amount to spent for that period
      • The difference between the budget and the reality
    • The multi period report shows
      • For the defined period the totals shown in the period reports
      • This report can be used to know your financial situation for the coming months.
    • Be able to register transactions
    • Be able to import transactions (currently only from one bank)

To be able to let more users make use of this application I am thinking about rebuilding it.

12

Technology requirements

I have some specific requirements for the technologies which I am going to use for this new version:

  • Have a tree data table (in Flex it is called an advanced datagrid) for visualizing an hierarchical data structure.
  • Low resource utilization on server side to reduce the cost of running the server
  • Be able to run on mobile phones as well (maybe a basic version)
  • Use an extremely scalable backend to service lots of users
  • Be able to show ads in the front-end to be able to earn the costs of the hosting.

Java EE6 and JavaFX

Since JEE6 is coming and the first beta releases of Glassfish and Netbeans are out I thought I try to use only Java EE6 technologies and try to make a basic test setup including client server communication and basic security. This will also give me the ability to deliver a small review of the new Java EE Edition.

In the past I have used a lot of different technologies to be able to use some kind of Dependency Injection (DI):

  • Self build DI framework (2003)
  • Spring Framework(2006)
  • Seam Framework (2007)

JEE6 is the first Java EE edition to deliver a DI framework which appear to not need additional frameworks. So I will use the Injection framework of JEE6 for Dependency Injection. For the client I choose JavaFX. Currently JavaFX 1.3 is in beta, but it at first glance it seems to fits my requirements. For the communication between JavaFX and JavaEE I used JSON with JAX-RS (new in EE6). This way I hope to get low bandwidth and CPU overhead. I used JSON before but at that time the protocol was brand new. Now it is integrated in JavaEE.

The back-end application

For creating the back-end application I started a Netbeans 6.9 beta web project. I only gave the project a name, selected the internal Glassfish 3.0.1b14 server and selected the JEE6 profile. First I created an User object which I can use to transfer data from the server to the client.

@XmlRootElement
public class User {
     private String username;
     private String password;

     public User(){} //needed for Jaxb objects

     public User(String username, String password){
         this.username = username;
         this.password = password;
     }
     ...getters and setters for the username and password
}

The only thing I needed to do to use this object in JSON communication is adding the @XmlRootElement annotation.
This is quite simple and saves a lot of work. The next thing I created was a service to look up account information

@SessionScoped
public class UserService implements Serializable{
    public UserService() {}

    private User user;

    public boolean login(String username,String password) {
       this.user = new User(username,password);
       return true;
    }

    public boolean isLoggedIn(){
        return(this.user != null);
    }

    public User getUser(){
        return user;
    }
}

Here I only needed to give the bean a scope. Since this bean is used for logging in and holding the account information, I make it a Session scoped bean. As you can see I did not connect it to a real back-end because I am going to choose the back-end later. I now have a login service I have to connect to a security mechanism. Since I do not want to use external frameworks I used Basic authentication. This works well because it integrates well with JavaFX. To be more secure I can use transport layer security (https). For the authentication I created a Servlet Filter

@WebFilter("/services/private/*")
public class SecurityFilter implements Filter {

    @Inject UserService userService;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        if (userService.isLoggedIn()) {
            chain.doFilter(request, response);
            return;
        } else {
            String username = null;
            String password = null;
            // Get the Authorization header, if one was supplied
            String authHeader = req.getHeader("Authorization");
            if (authHeader != null) {
                java.util.StringTokenizer st = new java.util.StringTokenizer(authHeader);
                if (st.hasMoreTokens()) {
                    String basic = st.nextToken();
                    if (basic.equalsIgnoreCase("Basic")) {
                        String credentials = st.nextToken();
                        sun.misc.BASE 64 Decoder decoder = new sun.misc.BASE 64 Decoder();
                        String userPass = new String(decoder.decodeBuffer(credentials));
                        int p = userPass.indexOf(":");
                        if (p != -1) {
                            username = userPass.sub string(0, p);
                            password = userPass.sub string(p + 1);
                        }
                    }
                }
            }
            if (username != null && password != null && !"".equals(username) && !"".equals(password)) {
                if (userService.login(username, password)) {
                    chain.doFilter(request, response);
                    return;
                }
            }

        }
        HttpServletResponse res = (HttpServletResponse) response;
        String s = "Basic realm=\"Login Rest Services - PersonalFinance\"";
        res.setHeader("WWW-Authenticate", s);
        res.setStatus(401);
    }
}

As you can see most of the code is quite simple and is only needed for decoding the basic authentication realm. The interesting JavaEE6 part is the @WebFilter("/services/private/*") annotation. With this annotation you can define where the filter will be used. It is no longer needed to define the filter in an web.xml file. The other interesting annotation is the @Inject UserService userService; with this annotation the UserService service is injected. Since the UserService has an @SessionScoped annotation this service will always be one instance for each session. The only part of the back-end that is left is the Rest Service itself. This service gives the current User bean back via JSON over REST.

@Path("private/account/")
@RequestScoped
public class Accounts implements Serializable{
    @Inject UserService userService;

    @GET
    @Path("show")
    @Produces("application/json")
    public User show(){
        return userService.getUser();
    }
}

As we can see implementing JSON over REST is easy.
The implementation of REST is done by using the @Path("private/account/") ,@GET and @Path("show") annotations. This produces an url /private/account/show for the show function. Which will accept the HTTP GET method.
To deliver the JSON output all I had to do was adding the @Produces("application/json") annotation and be sure that the User object is annotated with the @XmlRootElement annotation.

To test this simple back-end I deployed the application to the build in Glassfish server by clicking with the right mouse button on the project and selecting deploy.
After the deployment we can directly test the back-end:

As you can see we have to login. After typing an Username and password we see the JSON output.
The requirement to have a minimum of bandwidth overhead will be met. The JSON output is very small.
To test the performance I created a simple Jmeter test which just sends a correct REALM to login and shows the JSON output. The results where quite good.

45

I got 307 requests per second with 90% of the requests within 37 milliseconds without tuning anything and with 10 concurrent threads in Jmeter. The CPU load was 40% at that moment (Core i7 QC820). This proves for me that the overhead is low. With this case I simulated an worse case scenario where every request is a new session because I did not use an cookie manager in Jmeter.
7

Conclusions
The use of JavaEE6 for the back-end will be an appropriate choice. It is possible to develop very fast (I created the whole demo without any knowledge of the new features of JEE6 in less than 2 hours). And it meets the technical requirements in terms of overhead.
In the next part I will blog about the front-end in JavaFX 1.3.

Comments (1)

  1. Kenneth - Reply

    May 28, 2010 at 4:18 am

    I'm working on a project with similar architecture and but still
    looking for client technology. JavaFX, javascript framework like
    ExtJs, JSF and others are in consideration but none shows good
    enough solution for me. Really wonder yours "front-end" part
    to learn your experience.

Add a Comment