Is my J2EE/JavaEE application portable? Should I care? Hands-on Migration Use-Cases and Pitfalls (with GlassFish as the preferred target) Motivations ● The state of the economy creates opportunities ● ● Monolithic application servers are sooo 2007 ● ● Hard to have have developers and production agree on a product Tomcat is missing enterprise quality tools and Java EE technologies ● ● BEA and IBM raised their pricing in 2008 Monitoring+management / EJB, JMS, WebServices Production Open Source appservers are real ● ● JBoss, GlassFish, Geronimo, JOnAS Fully supported offerings Goals ● Two possible approaches ● ● ● Minimize risk (non-goals) ● ● ● Chose a new application server for all applications Start with a dual appserver strategy No rewrite if possible, do as little as possible No porting to Java EE 5 (or EE 6). Using backward compatibility Typical first questions ● ● ● “Is my application portable?” “How much $ to bridge the GAP?” “Does J2EE/JavaEE buy me vendor independence?” Yes! J2EE/JavaEE is portable ● Overall great portability ● ● ● The specification still leaves a few things open ● ● ● Some are meant to be, others unclear Some products are forgiving (lenient), others not Vendors offer “value-add/proprietary” APIs ● ● Some non-trivial applications run as-is on other container The value of the J2EE/JavaEE standard is real! Some obvious, others subtle People training, performance tuning ● Some partners offer ROI and commit to QoS A bit of methodology ● Understand the existing (moving) parts in use ● ● ● ● Assess dependencies ● ● ● Known and unknown APIs Frameworks ! Define a reasonable target (OS, JDK, AS) ● ● Application specifications, interview, … Technologies (Servlet, EJB, frameworks...) Applications complexity (# of tiers, legacy integration) Changing too many parameters is risky Set a reasonable and clear goal ● Unit, integration, performance, and user testing J2EE/Java EE Verifier ● Understand the level of portability of your app ● ● Static analysis of APIs and packaging ● ● ● ● List of assertions [1] Can be narrowed down to J2EE 1.4 or, say, web tier Produces warnings and errors “Just a tool” ● ● ● Part of every GlassFish (v2) distribution (+ admin integration), integrated into NetBeans, ANT tasks Don't expect a static tool to catch 100% of issues Yet a great tool to get you started ! Likely to become a top-level java.net project [1]: http://java.sun.com/j2ee/avk/5.0/assertions/Assertions.html GlassFish Verifier Example //Sample Application from WebSphere 6.x distribution $ verifier --portability was-BasicCalculator.ear $ Produces output in was-BasicCalculator.ear.txt --- NUMBER OF FAILURES/WARNINGS/ERRORS -----# of Failures : 0 # of Warnings : 0 # of Errors : 1 Error Name : Could not verify successfully. Error Description : java.lang.IllegalArgumentException: Invalid URL Pattern: BasicCalculatorServlet 3/30/08 Migrate2GlassFish ● ● Open source project at http://migrate2glassfish.dev.java.net Take over where the “verifier” left off ● ● ● ● ● ● Migration of deployment descriptors Runtime support for WebSphere and WebLogic custom JSP tags and proprietary APIs Converts (selected) configuration parameters Ant scripts for building/deploying the migrated app Other projects have similar initiatives Finite list of “source” application servers ● Mostly older versions No Brainers ● Tomcat applications should run unmodified on GlassFish v2 and v3 ● ... and with minimal changes on most containers ● Most containers “inherit” from Tomcat ● JSP/Servlet specifications are quite mature Deployment descriptors ● Specification allows for product-specific config ● ● ● Mostly used to tune the runtime (i.e. they do not change the behavior) EJB CMP mappings are not standard ● ● ● weblogic-application.xml, sun-web.xml, jboss-app.xml, ibm-ejb-access-bean.xml, ... Please move to JPA! :-) IBM tool-generated mappings can be problematic WebSphere validates deployment descriptors ● ● Validation failure can cause deployment or JSP compile errors GlassFish is no longer that strict Packaging issues (aka the ClassNotFoundError syndrom) ● Main issues ● Class-loader hierarchies are different – ● Default behavior can vary – – ● ● JBoss Unified ClassLoader (pre-v5) very forgiving WebSphere has parent first as default Even between different versions of the same product Be careful with JDK extensions (jre/lib/ext) Java modules and/or OSGi may fix the root of the problem in the future ● Likely to require application and library rewrites http://e-docs.bea.com/wls/docs100/programming/classloading.html WebLogic JBoss “unified” class-loader GlassFish http://docs.sun.com/app/docs/doc/819-3672/beade WebSphere Shared libraries ● IBM and BEA have a similar notion of shared libraries ● ● You could bundle the libraries in the application ● ● (much) bigger archive Understand the class-loader hierarchy and place the JARs in the appropriate location ● ● ● Libraries are not part of the WAR/JAR/EAR artifact Classes available to all applications No versioning of libraries GlassFish has a roughly equivalent option: $asadmin deploy --libraries ● Allows for multiple versions of libraries [1] Manifest Class-Path Manifest-Version: 1.0 Class-Path: library.jar ● ● Relative to the WAR/JAR expressing the dependency Does not work for EAR files ● ● ● ● But WebLogic documentation recommends this Ambiguous in the spec (“should” vs. “must” ?) Need to repackage for GlassFish or deploy with --libraries option (see discussion on shared libraries) [1]: http://java.sun.com/docs/books/tutorial/deployment/jar/downman.html Bundled libraries ● Application libraries can conflict with server libraries ● ● ● ● ● [1] Use endorsed classes when possible [2] GlassFish delegate="true|false" option ● ● Xerces, Xalan, log4j, etc... Yet another packaging/class-loading issue GlassFish uses JDK logging (limits conflicts) “false” is safe for web modules that do not interact with any other modules Repackaging required for other cases [1]: http://java.sun.com/javase/6/docs/technotes/guides/standards/ [2]: http://docs.sun.com/app/docs/doc/819-3672/beagb Security Manager ● ● Often turned off by default ● Performance impact, not developer friendly ● Yet useful to provide application isolation Does have an impact on class-loader visibility ● ● Need to explicitly grant application privileges to access libraries in server.policy Should be part of integration testing Tomcat's Valves ● A popular, yet proprietary, feature ● ● ● GlassFish supports Valves[1] ● ● ● ● Sort of low-level servlet filter Existing valves: Form Authentication, SSO, Dumper, Access Log, ... GlassFish v2 requires small Tomcat Valve change GlassFish v3 requires no change Defined in domain.xml's <virtual-server> or property in sun-web.xml Non-Tomcat-based products likely to require valve rewrites to servlet filters [1] : http://wiki.glassfish.java.net/Wiki.jsp?page=FaqTomcatValveConversion DB Pools ● Database resources are product-specific ● ● GlassFish offers : ● ● ● Admin tools and config files are not standard migrate2glassfish has facility to re-create pools asadmin and web console make it quite simple to create pools and datasources Implementation (nitty gritty) detail example ● ● ● “unshareable” JDBC connection scope May require XA on some servers Read-only connections often a better solution when no difference in : security attributes, isolation levels, character settings, or localization JNDI setup ● WebLogic T3 Protocol ● ● RMI/IIOP is the typical “standard” replacement ● ● ● And people think CORBA is “passé” ! :-) ORBs do not need to be the same on both ends (although that can help, see JVM discussion) In other cases, some (simple) tweaking required ● ● T3[1] is a proprietary WebLogic protocol, heavily used for rich (Swing) clients/server communication Typically set INITIAL_CONTEXT_FACTORY and PROVIDER_URL Don't forget about the ACC [1]: http://e-docs.bea.com/wls/docs103/client/t3.html WebSphere packaging <web-app> .. <servlet-mapping> <servlet-name>BasicCalcServlet</servlet-name> <url-pattern>BasicCalculatorServlet</url-pattern> </servlet-mapping> </web-app> WebSphere packaging <web-app> .. <servlet-mapping> <servlet-name>BasicCalcServlet</servlet-name> <url-pattern>/BasicCalculatorServlet</url-pattern> </servlet-mapping> </web-app> http://weblogs.java.net/blog/sekhar/archive/2008/02/migrating_websp.html (can be caught by the Verifier) Different JVMs ● VM startup options ● ● Java 1.4 vs. Java 5 vs. Java 6 ● ● ● Great portability, some known incompatibilities[1] Most products require a minimum JDK level (GlassFish requires Java 5 minimum) Tools (jconsole, jvmstat) ● ● -XX not standard and thus not always available Need Java 5 minimum, Java 6 better Subtle bugs ● IBM's BigDecimal fails to unmarshall in Sun ORB [1]: http://java.sun.com/j2se/1.5.0/compatibility.html Order in module loading ● The order in which Java EE modules are loaded varies between application servers ● ● ● Java EE 5 spec requires that all parts of the application are enabled and ready for service before any *user* requests are delivered to the application Order of servlet initialization in web application available using <load-on-startup> element Tip: deploy modules in disabled mode and enable them manually (or with a script) in the appropriate order http://weblogs.java.net/blog/sekhar Runtime Life-cycle ● Weblogic life-cycle events[1] ● ● ● Websphere Startup services ● ● ● Per-application or per-instance Defined in weblogic-application.xml [2] com.ibm.websphere.startupservice Available to EJB's GlassFish life-cycle listeners ● ● ● [3] Related to a GlassFish instance Defined in domain.xml, used for OpenESB, ... INIT, STARTUP, READY, SHUTDOWN, TERMINATION [1]: http://edocs.bea.com/wls/docs90/programming/lifecycle.html [2]: http://www.ibm.com/developerworks/websphere/library/techarticles/0401_beaton/ [3]: http://docs.sun.com/app/docs/doc/820-4336/beamc Runtime Life-cycle (cont.) ● ● JBoss has ServiceLifecycle [1] Tomcat too! [2] ● ● ● org.apache.catalina.LifecycleListener Mostly used internally (valves, cluster, comet, ...) GlassFish V2 has per-instance life-cycle events (not per-application) ● Even if event can be mapped to server/instance life-cycle event, need proper classpath and classloader configuration [1]: http://www.jboss.org/community/docs/DOC-12220 [2]: http://tomcat.apache.org/tomcat-5.5-doc/config/context.html Web Services ● Early days created legacy ● ● ● ● WS-I profiles ● ● ● Axis model (carry along may trigger conflicts) JAX-RPC (required even in Java EE 5) vs. JAX-WS DIME vs. SwA vs. MTOM Basic Profil mandates doc/lit web services Such profiles have no equivalent to Java TCK's Interop testing ● ● Sun has interops with Microsoft (project metro) [1] Apache has incubator project Stonehenge [2] [1]: http://metro.dev.java.net [2]: http://incubator.apache.org/stonehenge/ Out of scope (in this presentation) ● High Availability, performance ● ● ● Deployment infrastructure ● ● ● ● Load-balancing and session continuity Benchmarking and tuning ANT, CLI, provisioning, authentication, ... Clustering set-up OS-specific integration Management, monitoring ● ● ● Command-line tooling Web console Additional troubleshooting and monitoring tools Out of scope (cont.) (in this presentation) ● ● Development environment ● Moving to a modern versioning system ● Using continuous integration, ... Refactoring ● ● Java EE 5 (EJB 3, JAX-WS, ...) and EE 6 ESB, SSO, and other additional features Conclusion Betting on J2EE/JavaEE is a great investment Migration is very much doable even when you didn't think about portability in the first place References ● J2EE/JavaEE Verifier – http://docs.sun.com/app/docs/doc/819-3673/beadq ● ● ● Migrate2GlassFish – http://migrate2glassfish.dev.java.net Sekhar's blog – http://weblogs.java.net/blog/sekhar/ GlassFish – http://glassfish.org Questions ? alexis.mp@sun.com http://blogs.sun.com/alexismp http://blogs.sun.com/theaquarium