Sunday Monday Tuesday Wednesday Thursday Friday Saturday

Monday, December 10, 2012

Java EE 6 Web Profile. On the cloud. Easy.

Java SE is ok.
Java EE is evil.

That's what I always used to think. Well, not anymore, now. Let me share my experience.

Some weeks ago, I started thinking about porting a legacy spring+hibernate+tomcat application to a new platform : SAP NetWeaver Cloud. I known what you geeks out there are thinking : this post is getting worse. It starts with Java EE, not exactly a geeky thing, and now enters SAP, not exactly a geek company... Please, give me another ten minutes !

The configuration of the spring layer of my legacy application was xml-based (it was written before annotations came in the game). I was dreaded by the prospect of diving into - my own - xml horror again.

Then came this tweet :
and, some days later, this documentation. And I tried it out. And it worked. And I changed my mind about Java EE. There is a blog post by 'Bill the Plumber' that precisely describe what are my thoughts after this experience.

So much with the bla bla bla. Let's start coding! If you are in a hurry, clone the complete application from

Before cutting and pasting like mad, let's describe briefly what the code below is about. We will construct and deploy in the cloud (free) a tiny web application that:
1. logs in the user (sorry, you'll need a SAP Community Network account, do not worry it's free),
2. upon login, say 'hello' to the rest of the world on behalf of the user,
3. upon successive logins, instead of saying 'hello' again and again, merely store in a database how many 'hellos' were said, and
4. that's it.

To achieve that, we'll need one java interface, three java classes, one java server page, and a final touch of persistence.xml (for the database configuration) and web.xml (for security constraint wizardry).

For the sake of brevity, packages, imports, getters and setters are omitted from the code below. But, as just said, the complete source is available @ github

Write one POJO (complete class here):
public class Hello {
  private Long      id;
  private String    username;
  private Integer   counter;
  private Timestamp when;
  // ... getters and setters ...
Fairly obvious : for each username, this POJO will store in a counter how many time the user hit the index.jsp of our app, and when was the last time.

Annotate this POJO with JPA annotations (complete class here):
@NamedQueries( {
  @NamedQuery(name = "allHellos", query = "select h from Hello h"),
  @NamedQuery(name = "helloFromUsername", query = "select h from Hello h where h.username = :username")
public class Hello {
  private Long      id;
  @Column(name="A_USER", unique=true, nullable=false)
  private String    username;
  @Column(name="A_COUNTER", nullable=false)
  private Integer   counter;
  @Column(name="A_TIMESTAMP", nullable=false)
  private Timestamp when;

  public Hello() {
    this.counter = 1;
  // ... getters and setters ...
Write one interface that accesses the POJO (complete interface here)
public interface HelloDao {
  List<hello> getAll();
  Hello fromUsername(String username);
  Hello save(Hello hello);
Write one, annotated with EJB annotations, that implements the HelloDao interface (complete class here):
public class HelloBean implements HelloDao {

  private EntityManager em;

  public List<hello> getAll() {
    List<hello> hellos = (List<hello>)em.createNamedQuery("allHellos").getResultList();
    Collections.sort(hellos, new Comparator<hello>() {
      public int compare(Hello o1, Hello o2) {
        return o2.getWhen().compareTo(o1.getWhen()); // latest first
    return hellos;

  public Hello fromUsername(String username) {
    Query query = em.createNamedQuery("helloFromUsername");
    query.setParameter("username", username);
    Hello hello = null;
    try {
      hello = (Hello)query.getSingleResult();
    } catch (NoResultException ignored) {
    return hello;

  public Hello save(Hello hello) {
    hello = em.merge(hello);
    return hello;
Write one Java Servlet 3 Filter, that 1. bumps the counter upon login, and 2. exposes the HelloBean instance to the - coming soon - Java Server page (complete class here):
public final class HelloFilter implements Filter {

  HelloDao  helloDao;

  public void init(FilterConfig fConfig) throws ServletException {

  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  try {
    request.setAttribute("helloDao", helloDao);
    String username = ((HttpServletRequest)request).getRemoteUser();
    Hello hello = helloDao.fromUsername(username);
    if (hello == null) {
      hello = new Hello();
    } else {
    hello =;
    chain.doFilter(request, response);
  } finally {

  public void destroy() {
NB. in bold above, the magic plumbing done by our Java EE 6 Web Profile container between all these classes : @PersistenceContext EntityManager em;
@EJB HelloDao helloDao;

Write one persistence.xml JPA configuration (complete xml here)
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="" xmlns:xsi=""
  <persistence-unit name="adventscloud-persist" transaction-type="JTA">
      <property name="eclipselink.ddl-generation" value="create-or-extend-tables" />
Write one web.xml to trigger login when user access index.jsp and to inform the web application of the presence of a container managed database (complete xml here):
<?xml version="1.0" encoding="UTF-8"?>


      <web-resource-name>Protected Area</web-resource-name>
    <description>All SAP NetWeaver Cloud users</description>
Again, NB. above in bold the further magic plumbing: <jta-data-source>jdbc/DefaultDB</jta-data-source>

Finally, write one index.jsp java server page that displays all 'hellos' (complete page here):
<%@ taglib prefix="c"   uri="" %>
<%@ taglib prefix="fmt" uri="" %>
<!DOCTYPE html>
      <c:forEach var="hello" items="${requestScope.helloDao.all}" varStatus="status">
          <td><fmt:formatDate type="both" value="${hello.when}" /></td>
          <td>hello<c:if test = "${hello.counter > 1}">(s)</c:if> from</td>


We're nearly done ... two last things: 1. classpath hell, and 2. JPA 2.0 metamodel generation with javac -processor.

1. Classpath hell. In order to compile all this stuff, you'll need somehow to have the following jars on the classpath :
group             | artifact          | version
javax.persistence : persistence-api   : >= 1.0 
javax.ejb         : ejb-api           : >= 3.0 
javax.servlet     : javax.servlet-api : >= 3.0 
javax.servlet     : jstl              : >= 1.2
Of course the easiest way is to declare these dependencies in a maven project like mine, but if you are maven-averse, I took the time to hyperlink to the jars above to maven central to spare you some time chasing the jars.

2. JPA 2.0 metamodel generation with javac -processor. Finally , the build must be able to generate JPA 2.0 metamodel classes. Here I choose the eclipselink generator, as eventually eclipselink is the JPA implementation used by SAP NetWeaver Cloud. I believe that any JPA 2.0 compliant generator should do the job as well. Here also, maven do help, with the following xml fragment in the <build><plugins> section of the pom.xml:
Maven-averse can refer to eclipselink documentation about JPA 2.0 matamodel generation for alternative means to generate JPA 2.0 metamodel classes.

At this point, we have a adventscloud.war file that should run verbatim on any Java EE 6 Web Profile compliant container.

Among them is SAP NetWeaver Cloud. You can have a look at the application running at my lifelong-free trial instance of SAP NetWeaver Cloud. It is a bit richer than the code shown in this blog post, with a spark of twitter bootstrap bells and whistles. Follow the github ribbon in the app if you are interested by sparks.

If you'd like to get your lifelong-free trial instance of SAP NetWeaver Cloud, follow the initial steps described here.

I hope you enjoyed reading this post as much as I enjoyed writing it.

Salut à tous!


Meta: this post is part of the Java Advent Calendar and is licensed under the Creative Commons 3.0 Attribution license. If you like it, please spread the word by sharing, tweeting, FB, G+ and so on! Want to write for the blog? We are looking for contributors to fill all 24 slot and would love to have your contribution! Contact Attila Balazs to contribute!

[0] Java EE wins over spring
[1] Official Java EE compatibility page
[2] 'SAP Netweaver Cloud is Java EE 6 Web Profile Compatible' announcement on SAP Community Network


  1. Is the HelloDao interface really needed here? Couldn't you use HelloBean directly?

  2. Correct, HelloDao interface isn't mandator; the implementation class can be annotated with @LocalBean. Needs EJB 3.1, I believe. cf.