Java EE + Tomcat

Getting started with Apache TomEE

Originally appearing in December's JAX Magazine, Jonathan Gallimore tells us how to get started in Apache TomEE in the first part of this tutorial.

Introduction

Apache TomEE (pronounced "Tommy") is a new Java EE server, developed by the Apache Software Foundation, and as you can probably guess from its name, is result of taking Tomcat, and adding Java EE features: TomEE = Tomcat + Java EE. So, how it is different from other application servers?

A number of application servers use Tomcat to provide servlet functionality, and that's no bad thing – Tomcat is great servlet container. TomEE's approach is different – instead of embedding Tomcat into an application server, TomEE embeds EJB, CDI and the other Java EE features into Tomcat, giving you a fully compliant Web Profile server but keeping Tomcat as the top dog. The TomEE bundle is created by unzipping Tomcat, adding our jars, and adding a single listener to conf/server.xml and zipping the result back up.

There are three guiding principles behind the development of TomEE. They are:

  • Be small

  • Be certified

  • Be Tomcat

Each of these is really important to us, but the "be Tomcat" part particularly so – we are adding features to Tomcat, and it is important that TomEE does not lose the Tomcat identity. The deployment mechanism is the same as regular Tomcat (just drop your .war file in the webapps/ folder). Resources work in the same way – you can use TomEE's configuration file, but resources defined in server.xml or within your application’s context.xml also still work. Things that were previously impossible or required large amounts of work now work out of the box, such as making all Java EE security concepts like WebService or EJB security work seamlessly on Tomcat Realms.

This philosophy doesn’t just make things better in the server itself, but provides other advantages too. Since TomEE is simply an extended version of Tomcat, any tools that work with Tomcat, such as IDE tools like Eclipse WTP, all work with TomEE.

TomEE really is a genuine Tomcat server with all the Java EE Web Profile features added and nothing taken away.

Flavours

There are 3 different flavours of Apache TomEE available: Webprofile, JAX-RS, and Plus. Webprofile provides the smallest distribution (just 27MB) and is fully Java EE Web Profile compliant. JAX-RS builds on Web Profile, adding JAX-RS support with a trimmed down version of Apache CXF, and is also Web Profile certified. The Plus package provides all the features for TomEE that are available, including JMS, JAX-WS and JCA, but is not Java EE certified at this time.

The table below shows the different features available for the 3 different flavours.

Feature WebProfile JAX-RS Plus
Servlet 3.0 Yes Yes Yes
CDI Yes Yes Yes
EJB Yes Yes Yes
JPA Yes Yes Yes
JSF Yes Yes Yes
JSP Yes Yes Yes
JSTL Yes Yes Yes
JTA Yes Yes Yes
JavaMail Yes Yes Yes
Bean Validation Yes Yes Yes
JAX-RS No Yes Yes
JAX-WS No No Yes
JMS No No Yes
Connector No No Yes

Getting started

To get started, head over to Apache TomEE download page and grab one of the distributions. At the time of writing, version 1.5.0 is the latest. Once downloaded, extract the zip file somewhere on your machine. If you take a look at the folder structure, you'll probably notice straightaway how similar TomEE is to a regular copy of Tomcat. The usual catalina shell/batch script is in bin/, TomEE config files are in conf/, and applications are deployed by copying .war files to webapps/. Startup TomEE by changing to the bin/ folder and running ./catalina.sh run (or catalina.bat run if you are using Windows).

TomEE should start in a couple of seconds on a reasonable machine. Once it has started, open a browser and navigate to http://localhost:8080. If everything has started up correctly, the usual default Tomcat application will show. There is an additional button in this application that links to the TomEE console. The TomEE console provides some pages where you can check that your setup is working correctly and a JNDI browser.

Setting up a development environment using Eclipse

Let's fire up an IDE, and take a look at a simple program. I'm using Eclipse here, but other IDEs such as Netbeans and Intellij IDEA can be configured in the same way. I have the Java EE Eclipse package, which includes WTP, which can start up a number of different servers, deploy your code to them and automatically redeploy any changes you make. Setting up TomEE in Eclipse is the same process you would use to setup Tomcat.

Firstly, select the 'New server' link on the servers view.

Next, select Apache Tomcat 7, and change the name of the server if you wish:

On the next page of the wizard, select the installation directory where you unzipped the TomEE package to:

Optional tweaks

If you have configured Eclipse to use workspace metadata as opposed to taking over the TomEE installation, its a good idea to copy the files from the conf/ directory of the TomEE package to the workspace. When running in this mode, the configuration files are read from the conf/ directory in the workspace instead of from TomEE's conf directory. The WTP plugin helpfully copies a number of Tomcat configuration files to the workspace automatically, but does not pick up tomee.xml or system.properties.

To copy the necessary files to the workspace, right click on the localhost-config folder under the Servers project, and import the files from the conf/ directory.

By default, TomEE does not have the development parameter set for JSP compilation in web.xml, which means that JSP won't update on the fly as you save changes to them. To change this, open the web.xml file under the Servers->Tomcat v7.0 Server at localhost-config folder in the project explorer, and change the jsp servlet, so development mode is set to true as shown in Listing 1.

Listing 1: web.xml - configuring development mode for JSPs

 

  <servlet>
                <servlet-name>jsp</servlet-name>
                <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
                <init-param>
                        <param-name>fork</param-name>
                        <param-value>false</param-value>
                </init-param>
                <init-param>
                        <param-name>xpoweredBy</param-name>
                        <param-value>false</param-value>
                </init-param>
                <init-param>
                        <param-name>development</param-name>
                        <param-value>true</param-value>
                </init-param>
                <load-on-startup>3</load-on-startup>
        </servlet>

 

Sample application

So now we have a development environment setup, lets take a look at a simple example application. Apache TomEE comes with a number of example applications that demonstrate a number of different features available in Java EE. Currently there are over 100 examples, and these can serve as great starting point for learning new Java EE features. These are all available in the TomEE Subversion repository. I'm going to use the moviefun example in this article. Full source is available from http://tomee.apache.org/examples-trunk/moviefun/README.html. This sample is a simple web application using some of the features available in the Web Profile.

To start off with, the application has simple POJO which represents a Movie, and this is used by JPA to store and retrieve a Movie in the database. Listing 2 shows a movie POJO which has title, director, genre, year and rating attributes.

Listing 2: Movie Entity

 

@Entity
        public class Movie implements Serializable {

                @Id
                @GeneratedValue(strategy = GenerationType.AUTO)
                private long id;

                private String director;
                private String title;
                private int year;
                private String genre;
                private int rating;

                public Movie() {
                }

                // SNIP getter and setters below...
        }

 

This provides a simple object that can be persisted to the database, using JPA. To do this, a persistence context can be injected into a simple EJB or CDI bean, and that can be used to retrieve and persist Movie objects to the database.

Apache TomEE provides support for EJB from version 1. right up to version 3.1. EJB 3.0 made EJB creation much simpler than previous versions, and 3.1 builds on this further still. One of the new features is the "no-interface" view, which means that an EJB session bean no longer needs to provide an interface.

Listing 3 shows a simple stateless session EJB which can manage storing and retrieving data using JPA 2. This EJB is simple POJO that has been annotated with @Stateless (which is all that is needed to make it an EJB) and has an entity manager injected in by TomEE using the @PersistenceContext annotation.

Listing 3: Stateless session bean using JPA2

 

@Stateless
        public class MoviesBean {

                @PersistenceContext(unitName = "movie-unit")
                        private EntityManager entityManager;

                public Movie find(Long id) {
                        return entityManager.find(Movie.class, id);
                }

                public void addMovie(Movie movie) {
                        entityManager.persist(movie);
                }

                public void deleteMovie(Movie movie) {
                        entityManager.remove(movie);
                }

                public void deleteMovieId(long id) {
                        Movie movie = entityManager.find(Movie.class, id);
                        deleteMovie(movie);
                }

                public List<Movie> getMovies() {
                        CriteriaQuery<Movie> cq = entityManager.getCriteriaBuilder().createQuery(Movie.class);
                        cq.select(cq.from(Movie.class));
                        return entityManager.createQuery(cq).getResultList();
                }
        }

 

This class provides a few simple methods, firstly there are search, add and delete methods which delegate to the entity manager. The getMovies() method retrieves the complete set of movies from the database by constructing a simple JPA2 query. Notice that there are no boilerplate transaction begin or commit statements here. EJBs methods are transactional by default, so this is not necessary. TomEE is already saving you time!

This simple bean provides a simple API to interact with the database. Now we need something to use it! So let's look at moviefun's user interface. There's a number of ways a web frontend can interact with this EJB - for example it can be referenced by a JSF ManagedBean or you could look up the EJB from another MVC framework. To keep it simple, this example uses a servlet as shown in listing 4, which interacts with the EJB and then forwards the result on to a JSP.

As you'd expect, as TomEE has Tomcat 7 at its core, it supports the Servlet 3.0 spec. This allows us to create a class that extends javax.servlet.http.HttpServlet and is annotated with @WebServlet. Servlets and managed beans can have EJBs injected into their fields using the @EJB annotation on the field, and CDI beans can be injected in using the @Inject annotation. TomEE also supports @Inject constructor injection for Servlets, a feature which is being added for JavaEE 7.

Listing 4: Servlet with session bean injected

 

  @WebServlet("/moviefun/*")
        public class ActionServlet extends HttpServlet {
                private static final long serialVersionUID = -5832176047021911038L;

                @EJB
                private MoviesBean moviesBean;

                @Override
                protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
                                List<Movie> range = moviesBean.getMovies();
                                request.setAttribute("movies", movies);
                        }

                        request.getRequestDispatcher("WEB-INF/moviefun.jsp").forward(request, response);
                }
        }

 

We can then add a simple JSP to display the data and form to add a new entry, like the snippet in Listing 5.

Listing 5: JSP to render movies

 

 <div>
                <table>
                        <thead>
                                <tr>
                                        <th>Title</th>
                                        <th>Director</th>
                                        <th>Genre</th>
                                        <th>Rating</th>
                                        <th>Year</th>
                                </tr>
                        </thead>
                        <tbody>
                                <c:forEach items="${movies}" var="movie">
                                        <tr>
                                                <td><c:out value="${movie.title}" /></td>
                                                <td><c:out value="${movie.director}" /></td>
                                                <td><c:out value="${movie.genre}" /></td>
                                                <td><c:out value="${movie.rating}" /></td>
                                                <td><c:out value="${movie.year}" /></td>
                                        </tr>
                                </c:forEach>
                        </tbody>
                </table>
        </div>

 

So, with just three classes, and a JSP we are just about ready to go. We need one extra file, META-INF/persistence.xml, which will provide some basic information about the persistence unit that is injected into the EJB.

Listing 6: Persistence.xml

 

  <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
          <persistence-unit name="movie-unit">
            <jta-data-source>movieDatabase</jta-data-source>
            <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
            <class>org.superbiz.moviefun.Movie</class>

            <properties>
              <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
            </properties>
          </persistence-unit>
        </persistence>

 

The persistence.xml example shown in Listing 6 indicates the @Entity classes being used (org.superbiz.moviefun.Movie in this case), and specifies that OpenJPA should build the schema for us in the database automatically if it does not already exist.

Deploying the app

We're now ready to deploy the application. You can add this module to the server, and start the server up.

You should see the application start up without any errors. The URL for the application will follow the .war filename (or project in Eclipse), so for example, example.war will be deployed to http://localhost:8080/example/.

Look Mom, no EARs!

You will notice that everything is in one module which will just be packaged into one single WAR file. There is no need to construct an EAR file with the EJB separated out into its own JAR, as has been the case with previous versions of Java EE. This is a feature that actually originated from TomEE, which has had it for a number of years, and was one of its first contributions to JavaEE.

All your memory are belong to you!

It’s worth pointing out at this point that TomEE is running with the default memory parameters – on my Mac running a 64bit server JDK 1.6, that's 128MB max by default, and TomEE running the moviefun example, uses around just 30MB of that.

That leaves plenty of memory available for your application. TomEE is actually certified using Amazon EC2 micro instances, each of which have just 613MB of RAM – not very much by today's standards. But using TomEE as your application server, plenty of that 613MB is available for your application to use. We have even been able to run TomEE and the moviefun example application on a Raspberry Pi with 256MB of RAM, which costs just $35. Who says Java EE is heavy or expensive?

Database configuration

You may also have noticed that we have developed and deployed a database application, without actually configuring anything in TomEE whatsoever. If you restart the TomEE server within Eclipse, you'll notice that all the data in the application is persisted. So where exactly is that data being stored, and how is the data source configured?

TomEE is configured using a single XML configuration file, tomee.xml, which lives in the conf/ directory. If you take a look at this file, you'll see a few different things configured with the default settings – EJB pools, datasources and resource adapters. The syntax is maybe slightly different to other XML configuration files you may have seen for other application servers. It is based around the configuration style for the Apache httpd server, and aims to be as easily human readable as possible. Times, such as the timeout time for a bean pool, rather than being specified in milliseconds, can be be expressed as a combination of any time units you like, for example "1 hour and 10 minutes and 30 seconds".

Defining a datasource can be done by adding a section to tomee.xml like Listing 7.

Listing 7: Configuring a datasource in tomee.xml

 

 <Resource id="movieDatabase" type="DataSource">
          JdbcDriver com.mysql.jdbc.Driver
          JdbcUrl jdbc:mysql://localhost:3306/moviefun
          UserName username
          Password password
          JtaManaged true
        </Resource>

 

Set the JdbcDriver setting to match the class provided by the JDBC driver you wish to use, and set the JdbcUrl, UserName and Password settings to match your database. You will also need to deploy the JDBC driver you wish to use, which you can do simply by dropping the jar for it in the TomEE/lib directory.

The Resource ID should match the <jta-data-source> or <non-jta-data-source> defined in the persistence.xml file. If no matching resources are found in the tomee.xml file, the default database will be used, which is what has been happening. The default database is a file based instance of HSQLDB that uses the data/ directory. This file can also be used to configure JMS queues and topics, and any other resources you may wish to use in your application.

Configuration settings can also be specified via system properties. The datasource example can be specified as system properties as JAVA_OPTS like this:  

-DmovieDatabase.JdbcDriver=com.mysql.jdbc.Driver

 -DmovieDatabase.JdbcUrl=jdbc:mysql://localhost:3306/moviefun

-DmovieDatabase.UserName=username -DmovieDatabase.Password=password

Or it can be added to conf/system.properties. More information and list of built in system properties is available on the TomEE website.

Security

TomEE tightly integrates Java EE security in a way that is seamless and consistent across the web tier, EJBs and webservices. It is really simple to add to an application and any custom Tomcat Realm implementations such as the JDBC, LDAP or MongoDB backed Realms will work in TomEE with no changes. Alternatively, custom security modules are also supported via a JAAS login.config file in the conf/ directory. Security using basic HTTP authentication can be added to the moviefun example by following these steps:

Add a user and role to the tomcat-users.xml file:

<user username="movies" password="movies" roles="moviefun"/>

Add some security configuration to web.xml, as shown in Listing 8.

Listing 8: web.xml security configuration

 

  <login-config>
                <auth-method>BASIC</auth-method>
                <realm-name>UserDatabase</realm-name>
        </login-config>

        <security-role>
                <role-name>moviefun</role-name>
        </security-role>

        <security-constraint>
                <web-resource-collection>
                        <web-resource-name>Everything</web-resource-name>
                        <url-pattern>/*</url-pattern>
                </web-resource-collection>
                <auth-constraint>
                        <role-name>moviefun</role-name>
                </auth-constraint>
                <user-data-constraint>
                        <transport-guarantee>NONE</transport-guarantee>
                </user-data-constraint>
        </security-constraint>

 

And finally add @RolesDeclared to the MoviesBean class, and @RolesAllowed either to the MoviesBean class, or to the individual methods you wish to grant access to, as shown in Listing 9.

Listing 9: adding roles to session bean

 

@Stateless
        @DeclareRoles(value = { "moviefun" })
        public class MoviesBean {

                @RolesAllowed(value = { "moviefun" })
                public List<Movie> findAll(int firstResult, int maxResults) {
                        ...
                }
        }

 

This configuration will require authentication to access any of the page within the application using a basic authentication dialog in the web browser. The username and password will be checked against the UserDatabase realm in Tomcat, which uses the tomcat-users.xml file. Finally TomEE will pass the logged in principal and associated roles to the EJB. Only users with the allowed roles will be able to invoke the methods on the EJB. Invoking the methods on the EJB from a remote client will also require the username and password to be sent, and will be authenticated against the UserDatabase realm.

Editor's Note: Keep your eyes peeled for the second part of the tutorial tomorrow focusing on TomEE testing!

Author Bio: Jon is an Open Source and Java EE enthusiast working for Weatherbys Ltd in the UK. As an Open Source consumer-turned-contributor, Jon has been a committer for the Apache TomEE and OpenEJB projects for the past four years, and has worked on a number of different features including the early Tomcat 7 integration in TomEE, parts of the EJB 3.1 compliance, TomEE Arquillian adapters and the OpenEJB Eclipse Plugin. When not grinding away at work by day, and burning the midnight oil on Apache TomEE at night, Jon enjoys cooking, watching Formula One, and playing the occasional game of golf.

This article appeared in JAX Magazine:TomEE - download that and other issues here.

Jonathan Gallimore
Jonathan Gallimore

What do you think?

JAX Magazine - 2014 - 05 Exclucively for iPad users JAX Magazine on Android

Comments

Latest opinions