[[Migrate_Order_Application_from_EAP5]] = Porting the Order Application from EAP 5.1 to WildFly {wildflyVersion} Andy Miller ported an example Order application that was used for performance testing from EAP 5.1 to WildFly {wildflyVersion}. These are the notes he made during the migration process. [[overview-of-the-application]] == Overview of the application The application is relatively simple. it contains three servlets, some stateless session beans, a stateful session bean, and some entities. In addition to application code changes, modifications were made to the way the EAR was packaged. This is because WildFly removed support of some proprietary features that were available in EAP 5.1. [[summary-of-changes]] == Summary of changes [[code-changes]] === Code Changes [[modify-jndi-lookup-code]] ==== Modify JNDI lookup code Since this application was first written for EAP 4.2/4.3, which did not support EJB reference injection, the servlets were using pre-EE 5 methods for looking up stateless and stateful session bean interfaces. While migrating to WildFly, it seemed a good time to change the code to use the @EJB annotation, although this was not a required change. The real difference is in the lookup name. WildFly only supports the new EE 6 portable JNDI names rather than the old EAR structure based names. The JNDI lookup code changed as follows: Example of code in the EAP 5.1 version: [source, java] ---- try { context = new InitialContext(); distributionCenterManager = (DistributionCenterManager) context.lookup("OrderManagerApp/DistributionCenterManagerBean/local"); } catch(Exception lookupError) { throw new ServletException("Couldn't find DistributionCenterManager bean", lookupError); } try { customerManager = (CustomerManager) context.lookup("OrderManagerApp/CustomerManagerBean/local"); } catch(Exception lookupError) { throw new ServletException("Couldn't find CustomerManager bean", lookupError); }   try { productManager = (ProductManager) context.lookup("OrderManagerApp/ProductManagerBean/local"); } catch(Exception lookupError) { throw new ServletException("Couldn't find the ProductManager bean", lookupError); } ---- Example of how this is now coded in WildFly: [source, java] ---- @EJB(lookup="java:app/OrderManagerEJB/DistributionCenterManagerBean!services.ejb.DistributionCenterManager") private DistributionCenterManager distributionCenterManager;   @EJB(lookup="java:app/OrderManagerEJB/CustomerManagerBean!services.ejb.CustomerManager") private CustomerManager customerManager;   @EJB(lookup="java:app/OrderManagerEJB/ProductManagerBean!services.ejb.ProductManager") private ProductManager productManager; ---- In addition to the change to injection, which was supported in EAP 5.1.0, the lookup name changed from: [source, java] ---- OrderManagerApp/DistributionCenterManagerBean/local ---- to: [source, java] ---- java:app/OrderManagerEJB/DistributionCenterManagerBean!services.ejb.DistributionCenterManager ---- All the other beans were changed in a similar manner. They are now based on the portable JNDI names described in EE 6. [[modify-logging-code]] === Modify logging code The next major change was to logging within the application. The old version was using the commons logging infrastructure and Log4J that is bundled in the application server. Rather than bundling third-party logging, the application was modified to use the new WildFly Logging infrastructure. The code changes themselves are rather trivial, as this example illustrates: Old JBoss Commons Logging/Log4J: [source, java] ---- private static Log log = LogFactory.getLog(CustomerManagerBean.class); ---- New WildFly Logging [source, java] ---- private static Logger logger = Logger.getLogger(CustomerManagerBean.class.toString()); ---- Old JBoss Commons Logging/Log4J: [source, java] ---- if(log.isTraceEnabled()) { log.trace("Just flushed " + batchSize + " rows to the database."); log.trace("Total rows flushed is " + (i+1)); } ---- New WildFly Logging: [source, java] ---- if(logger.isLoggable(Level.TRACE)) { logger.log(Level.TRACE, "Just flushed " + batchSize + " rows to the database."); logger.log(Level.TRACE, "Total rows flushed is " + (i+1)); } ---- In addition to the code changes made to use the new AS7 JBoss log manager module, you must add this dependency to the `MANIFEST.MF` file as follows: [source, java] ---- Manifest-Version: 1.0 Dependencies: org.jboss.logmanager ---- [[modify-the-code-to-use-infinispan-for-2nd-level-cache]] === Modify the code to use Infinispan for 2nd level cache Jboss Cache has been replaced by Infinispan for 2nd level cache. This requires modification of the `persistence.xml` file. This is what the file looked like in EAP 5.1: [source, java] ---- ---- This is how it was modified to use Infinispan for the same configuration: [source, java] ---- ENABLE_SELECTIVE ---- Most of the properties are removed since they will default to the correct values for the second level cache. See https://docs.jboss.org/author/display/AS71/JPA+Reference+Guide#JPAReferenceGuide-UsingtheInfinispansecondlevelcache["Using the Infinispan second level cache"] for more details. That was the extent of the code changes required to migrate the application to AS7. [[ear-packaging-changes]] === EAR Packaging Changes Due to modular class loading changes, the structure of the existing EAR failed to deploy successfully in WildFly. The old structure of the EAR was as follows: [source, java] ---- $ jar tf OrderManagerApp.ear META-INF/MANIFEST.MF META-INF/application.xml OrderManagerWeb.war OrderManagerEntities.jar OrderManagerEJB.jar META-INF/ ---- In this structure, the entities and the `persistence.xml` were in one jar file, `OrderManagerEntities.jar`, and the stateless and stateful session beans were in another jar file, `OrderManagerEJB.jar`. This did not work due to modular class loading changes in WildFly. There are a couple of ways to resolve this issue: 1. Modify the class path in the `MANIFEST.MF` 2. Flatten the code and put all the beans in one JAR file. The second approach was selected because it simplified the EAR structure: [source, java] ---- $ jar tf OrderManagerApp.ear META-INF/application.xml OrderManagerWeb.war OrderManagerEJB.jar META-INF/ ---- Since there is no longer an `OrderManagerEntities.jar` file, the `applcation.xml` file was modified to remove the entry. An entry was added to the `MANIFEST.MF` file in the `OrderManagerWeb.war` to resolve another class loading issue resulting from the modification to use EJB reference injection in the servlets. [source, java] ---- Manifest-Version: 1.0 Dependencies: org.jboss.logmanager Class-Path: OrderManagerEJB.jar ---- The `Class-Path` entry tells the application to look in the `OrderManagerEJB.jar` file for the injected beans. [[summary]] === Summary Although the existing EAR structure could have worked with additional modifications to the `MANIFEST.MF` file, this approach seemed more appealing because it simplified the structure while maintaining the web tier in its own WAR. The source files for both versions is attached so you can view the changes that were made to the application.