Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>When we set out with the goal to Java EE 6 certify Apache Tomcat as <a href="http://tomee.apache.org/comparison.html">Apache TomEE</a>, here are some of the gaps we had to fill in order to finally pass the Java EE 6 TCK.</p> <p>Not a complete list, but some highlights that might not be obvious even with the existing answers.</p> <h2>No TransactionManager</h2> <p>Transaction Management is definitely required for any certified server. In any web component (servlet, filter, listener, jsf managed bean) you should be able to get a <code>UserTransaction</code> injected like so:</p> <ul> <li><code>@Resource UserTransaction transaction;</code></li> </ul> <p>You should be able use the <code>javax.transaction.UserTransaction</code> to create transactions. All the resources you touch in the scope of that transaction should all be enrolled in that transaction. This includes, but is not limited to, the following objects:</p> <ul> <li><code>javax.sql.DataSource</code></li> <li><code>javax.persistence.EntityManager</code></li> <li><code>javax.jms.ConnectionFactory</code></li> <li><code>javax.jms.QueueConnectionFactory</code></li> <li><code>javax.jms.TopicConnectionFactory</code></li> <li><code>javax.ejb.TimerService</code></li> </ul> <p>For example, if in a servlet you start a transaction then:</p> <ul> <li>Update the database</li> <li>Fire a JMS message to a topic or queue</li> <li>Create a Timer to do work at some later point</li> </ul> <p>.. and then one of those things fails or you simply choose to call <code>rollback()</code> on the <code>UserTransaction</code>, then all of those things are undone.</p> <h2>No Connection Pooling</h2> <p>To be very clear there are two kinds of connection pooling:</p> <ul> <li>Transactionally aware connection pooling</li> <li>Non-Transactionally aware connection pooling</li> </ul> <p>The Java EE specs do not strictly require connection pooling, however if you have connection pooling, it should be transaction aware or you will lose your transaction management.</p> <p>What this means is basically:</p> <ul> <li>Everyone in the same transaction should have the same connection from the pool</li> <li>The connection should not be returned to the pool until the transaction completes (commit or rollback) regardless if someone called <code>close()</code> or any other method on the <code>DataSource</code>.</li> </ul> <p>A common library used in Tomcat for connection pooling is commons-dbcp. We wanted to also use this in TomEE, however it did not support transaction-aware connection pooling, so we actually added that functionality into commons-dbcp (yay, Apache) and it is there as of commons-dbc version 1.4.</p> <p>Note, that adding commons-dbcp to Tomcat is still not enough to get transactional connection pooling. You still need the transaction manager and you still need the container to do the plumbing of registering connections with the <code>TransactionManager</code> via <code>Synchronization</code> objects.</p> <p>In Java EE 7 there's talk of adding a standard way to encrypt DB passwords and package them with the application in a secure file or external storage. This will be one more feature that Tomcat will not support.</p> <h2>No Security Integration</h2> <p>WebServices security, JAX-RS SecurityContext, EJB security, JAAS login and JAAC are all security concepts that by default are not "hooked up" in Tomcat even if you individually add libraries like CXF, OpenEJB, etc.</p> <p>These APIs are all of course suppose to work together in a Java EE server. There was quite a bit of work we had to do to get all these to cooperate and to do it on top of the Tomcat <code>Realm</code> API so that people could use all the existing Tomcat <code>Realm</code> implementations to drive their "Java EE" security. It's really still Tomcat security, it's just very well integrated.</p> <h2>JPA Integration</h2> <p>Yes, you can drop a JPA provider into a .war file and use it without Tomcat's help. With this approach you will not get:</p> <ul> <li><code>@PersistenceUnit EntityManagerFactory</code> injection/lookup</li> <li><code>@PersistenceContext EntityManager</code> injection/lookup</li> <li>An <code>EntityManager</code> hooked up to a transactional aware connection pool</li> <li>JTA-Managed <code>EntityManager</code> support</li> <li>Extended persistence contexts</li> </ul> <p>JTA-Managed <code>EntityManager</code> basically mean that two objects in the same transaction that wish to use an <code>EntityManager</code> will both see the same <code>EntityManager</code> and there is no need to explicitly pass the <code>EntityManager</code> around. All this "passing" is done for you by the container.</p> <p>How is this achieved? Simple, the <code>EntityManager</code> you got from the container is a fake. It's a wrapper. When you use it, it looks in the current transaction for the real <code>EntityManager</code> and delegates the call to that <code>EntityManager</code>. This is the reason for the mysterious <code>EntityManager.getDelegate()</code> method, so users can get the <strong>real</strong> EntityManager if they want and make use of any non-standard APIs. Do so with great care of course and never keep a reference to the delegate <code>EntityManager</code> or you will have a serious memory leak. The delegate <code>EntityManager</code> will normally be flushed, closed, cleaned up and discarded when a transaction completes. If you're still holding onto a reference, you will prevent garbage collection of that <code>EntityManager</code> and possibly all the data it holds.</p> <ul> <li>It's always safe to hold a reference to a <code>EntityManager</code> you got from the container</li> <li>Its not safe to hold a reference to <code>EntityManager.getDelegate()</code></li> <li>Be very careful holding a reference to an <code>EntityManager</code> you created yourself via an <code>EntityManagerFactory</code> -- you are 100% responsible for its management.</li> </ul> <h2>CDI Integration</h2> <p>I don't want to over simplify CDI, but I find it is a little too big and many people have not take a serious look -- it's on the "someday" list for many people :) So here is just a couple highlights that I think a "web guy" would want to know about.</p> <p>You know all the putting and getting you do in a typical webapp? Pulling things in and out of <code>HttpSession</code> all day? Using <code>String</code> for the key and continuously casting objects you get from the <code>HttpSession</code>. You've probably go utility code to do that for you.</p> <p>CDI has this utility code too, it's called <code>@SessionScoped</code>. Any object annotated with <code>@SessionScoped</code> gets put and tracked in the <code>HttpSession</code> for you. You just request the object to be injected into your Servlet via <code>@Inject FooObject</code> and the CDI container will track the "real" FooObject instance in the same way I described the transactional tracking of the <code>EntitityManager</code>. Abracadabra, now you can delete a bunch of code :)</p> <p>Doing any <code>getAttribute</code> and <code>setAttribute</code> on <code>HttpServletRequest</code>? Well, you can delete that too with <code>@RequestScoped</code> in the same way.</p> <p>And of course there is <code>@ApplicationScoped</code> to eliminate the <code>getAttribute</code> and <code>setAttribute</code> calls you might be doing on <code>ServletContext</code></p> <p>To make things even cooler, any object tracked like this can implement a <code>@PostConstruct</code> which gets invoked when the bean gets created and a <code>@PreDestroy</code> method to be notified when said "scope" is finished (the session is done, the request is over, the app is shutting down).</p> <p>CDI can do a lot more, but that's enough to make anyone want to re-write an old webapp.</p> <h2>Some picky things</h2> <p>There are some things added in Java EE 6 that are in Tomcats wheelhouse that were not added. They don't require big explanations, but did account for a large chunk of the "filling in the gaps".</p> <ul> <li>Support for <code>@DataSourceDefinition</code></li> <li>Support for Global JNDI (<code>java:global</code>, <code>java:app</code>, <code>java:module</code>)</li> <li>Enum injection via <code>@Resource MyEnum myEnum</code> and </li> <li>Class injection via <code>@Resource Class myPluggableClass</code> and </li> <li>Support for <code>@Resource(lookup="foo")</code></li> </ul> <p>Minor points, but it can be incredibly useful to define <code>DataSource</code> in the app in a portable way, share JNDI entries between webapps, and have the simple power to say "look this thing up and inject it"</p> <h2>Conclusion</h2> <p>As mentioned, not a complete list. No mention of EJB, JMS, JAX-RS, JAX-WS, JSF, Bean Validation and other useful things. But at least some idea of the things often overlooked when people talk about what Tomcat is and is not.</p> <p>Also be aware that what you might have thought of as "Java EE" might not match the actual definition. With the Web Profile, Java EE has shrank. This was <strong>deliberately</strong> to address "Java EE is too heavy and I don't need all that".</p> <p>If you cut EJB out of the Web Profile, here's what you have left:</p> <ul> <li>Java Servlets </li> <li>Java ServerPages (JSP) </li> <li>Java ServerFaces (JSF) </li> <li>Java Transaction API (JTA) </li> <li>Java Persistence API (JPA) </li> <li>Java Contexts and Dependency Injection (CDI) </li> <li>Bean Validation </li> </ul> <p>It's a pretty darn useful stack.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload