Migrate from GlassFish to WildFly

In this blog I just want to post some of my thoughts about migrating from GlassFish to WildFly. The main issue here for me is to deploy an existing EAR currently running on GlassFish 3. This EAR contains EJBs, Web, and REST modules and includes TimerServices, Security Issues and custom servlets. So it’s not the easy hello-world example.

I am working on Linux Debian 7 and using Open JDK 1.7.0_55. The examples show the configuration for the Imixs Office Workflow Suite.

Installation and starting

Installation of WildFly is as easy as it was for GlassFish. Just unpack the WildFly archive (wildfly-8.0.0.Final.tar.gz) into your target folder (e.g. /opt).

To start WildFly 8 using the default web profile configuration in “standalone” mode, change directory to [WILDFLY_INSTALL]/bin/  and run:

./standalone.sh

Now you can open WildFly from your browser: http://localhost:8080/

Configure Port-Offset

WildFly uses the same http port number (8080) as GlassFish. To start WildFly with different port base you can use the run option “jboss.socket.binding.port-offset”

./standalone.sh -Djboss.socket.binding.port-offset=10000

this will start the web container at: http://localhost:18080/

Alternatively you can change the socket-binding in standalone.xml file to define a general port offset:

<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:1000}">
        <socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
        <socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/>
        <socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>
        <socket-binding name="http" port="${jboss.http.port:8080}"/>
        <socket-binding name="https" port="${jboss.https.port:8443}"/>
        <socket-binding name="txn-recovery-environment" port="4712"/>
        <socket-binding name="txn-status-manager" port="4713"/>
        <outbound-socket-binding name="mail-smtp">
            <remote-destination host="localhost" port="25"/>
        </outbound-socket-binding>
       </socket-binding-group>

A non conflicting value beside a GlassFish installation is a port-offset of 1

Admin Console

WildFly comes with a Admin Console like GlassFish. Before you can open the Admin Console you need to add a ‘Management user’. Run the following script form the bin folder and enter the requested information:

./add-user.sh

Now you can open the administration consol: http://localhost:8080/console

JPA – EclipseLink

As I have developed JEE on GlassFish I use EclipseLink as the JPA implementation. JBoss and Wildfly use in default Hibernate. Both implementation shuld do the same thing but it is a good idea to stay with EclipseLink, if you started with it. You can add EclipseLink very easy by adding eclipselink.jar (eclipselink-2.5.1.jar) into the folder

modules/system/layers/base/org/eclipse/persistence/main

and update the configuration in

modules/system/layers/base/org/eclipse/persistence/main/module.xml

Add the tag <resource-root path=”eclipselink.jar”/> into the section ‘resources as described here.

.....
<module xmlns="urn:jboss:module:1.3" name="org.eclipse.persistence">
  <resources>
    <resource-root path="jipijapa-eclipselink-1.0.1.Final.jar"/>
    <resource-root path="eclipselink.jar"/>
  </resources>
.....

For wildfly 9 you need to change the resource-root like this:

<resource-root path="eclipselink.jar">
        <filter>
                <exclude path="javax/**" />
        </filter>
</resource-root>

See also stackoverflow question.

Using “org.eclipse.persistence.jpa.PersistenceProvider”

If you use the ‘org.eclipse.persistence.jpa.PersistenceProvider’ in the persistence.xml it is important to add the org.jipijapa.eclipselink.JBossArchiveFactoryImpl afterwards with the following command form the WildFly bin/ folder when WildFly is running:

./jboss-cli.sh --connect '/system-property=eclipselink.archive.factory:add(value=org.jipijapa.eclipselink.JBossArchiveFactoryImpl)'

Note: If you run WildFly with a different portrange you need to add the ‘controller’ param to the jboss-cli script. See the following example accessing the admin console with port 9991:

./jboss-cli.sh --connect controller=127.0.0.1:9991 '/system-property=eclipselink.archive.factory:add(value=org.jipijapa.eclipselink.JBossArchiveFactoryImpl)'

This command will change the standalone.xml configuration file and adds the following entry:

<system-properties>
 ...
 <property name="eclipselink.archive.factory" value="org.jipijapa.eclipselink.JBossArchiveFactoryImpl"/>
</system-properties>

You can find additional Information here.

Datasource Configuration (MySQL)

The Datasource management is one of the things which is really much easier to use as in GlassFish Server. For example to use the MySQL JDBC driver you can simply deploy the driver jar into Wildfly. In the web inferface from WildFly choose:

Runtime->Server->Manage Deployments

and add your mysql Driver jar (e.g mysql-connector-java-5.1.7-bin.jar) as a new deployment and enable the deployment unit. That’s it.

To add a Datasource its the best way to edit the standalone.xml file and add a new database section like this example

<datasource jta="true" jndi-name="java:/jdbc/imixs-workflow" pool-name="imixs_workflow" enabled="true" use-ccm="true" statistics-enabled="false">
 <connection-url>jdbc:mysql://localhost:3306/imixs?autoReconnect=true</connection-url>
 <driver-class>com.mysql.jdbc.Driver</driver-class>
 <driver>mysql-connector-java-5.1.7-bin.jar</driver>
 <security>
 <user-name>user</user-name>
 <password>xxx</password>
 </security>
 <validation>
   <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker"></valid-connection-checker>
   <validate-on-match>true</validate-on-match>
   <background-validation>false</background-validation>
 </validation>
 <timeout>
 <set-tx-query-timeout>false</set-tx-query-timeout>
 <blocking-timeout-millis>0</blocking-timeout-millis>
 <idle-timeout-minutes>0</idle-timeout-minutes>
 <query-timeout>0</query-timeout>
 <use-try-lock>0</use-try-lock>
 <allocation-retry>0</allocation-retry>
 <allocation-retry-wait-millis>0</allocation-retry-wait-millis>
 </timeout>
 <statement>
 <share-prepared-statements>false</share-prepared-statements>
 </statement>
 </datasource>

Adding a database using the web console is a little bit strange.

Note: For MySQL the valid-connection-checker class ‘org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker’ is the recommended way to avoid connection failures when the MySQL Server is restarted. An alternative is adding  the query param  ‘?autoReconnect=true’ to the JDBC url. See also discussion here.

Security Realm

The Security Realm configuration is quite simple in WildFly. You can configure the realm in the standalone.xml file.

For a JDBC Security Realm, which is similar to a GlassFish JDBCRealm the following module options are important:

  • dsJndiName=java:/jdbc/imixs_office
  • hashAlgorithm=SHA-256
  • hashEncoding=hex
  • principalsQuery=select PASSWORD from USERID where ID=?
  • rolesQuery=select GROUP_ID,’Roles’ from USERID_USERGROUP where ID=?
  • unauthenticatedIdentity=anonymous

The security domain configuration in the standalone.xml configuraiton file than looks like this:

<security-domain name="imixsrealm">
 <authentication>
 <login-module code="Database" flag="required">
 <module-option name="dsJndiName" value="java:/jdbc/imixs_office"/>
 <module-option name="hashAlgorithm" value="SHA-256"/>
 <module-option name="hashEncoding" value="hex"/>
 <module-option name="principalsQuery" value="select PASSWORD from USERID where ID=?"/>
 <module-option name="rolesQuery" value="select GROUP_ID,'Roles' from USERID_USERGROUP where ID=?"/>
 <module-option name="unauthenticatedIdentity" value="anonymous"/>
 </login-module>
 </authentication>
 </security-domain>

To finish the configuration, add the file jboss-web.xml in the folder WEB-INF of your web module with the following content. his file is used to define the security domain used by the application:

<?xml version="1.0" encoding="UTF-8"?>
 <jboss-web>
     <security-domain>imixsrealm</security-domain>
</jboss-web>

Role Mapping

In different to GlassFish for WildFly there is no explicit role-group mapping necessary. So you need no special deployment descriptor like the /WEB-INF/glassfish-application.xml. The Roles defined by a application can be directly used in the security configuration for a user.

See also: http://wildfly.org/news/2014/02/06/GlassFish-to-WildFly-migration/

In case you have existing group mappings (e.g. in a database group table or in a LDAP directory) you can add the mapping by defining a file app.properties, where app is the name of the security domain, as defined above. Save this file in the folder WILDFLY_HOME/standalone/configuration or WILDFLY_HOME/domain/configuration to be taken into account.

This is an example of my file imixsrealm.properties which mapps the group names to roles defined in my application:

IMIXS-WORKFLOW-Reader=org.imixs.ACCESSLEVEL.READERACCESS
IMIXS-WORKFLOW-Author=org.imixs.ACCESSLEVEL.AUTHORACCESS
IMIXS-WORKFLOW-Editor=org.imixs.ACCESSLEVEL.EDITORACCESS
IMIXS-WORKFLOW-Manager=org.imixs.ACCESSLEVEL.MANAGERACCESS

Groups are listed on the left of the equal operator and roles are listed on the right. In the example above, users in the group ‘IMIXS-WORKFLOW-Reader’ fulfill the role ‘org.imixs.ACCESSLEVEL.READACCESS’.

Note: To activate this role mapping the security domain need a login-module section for the RoleMapping:

<security-domain name="imixsrealm">
 <authentication>
 <login-module code="Database" flag="required">
 <module-option name="dsJndiName" value="java:/jdbc/imixs_office"/>
 <module-option name="hashAlgorithm" value="SHA-256"/>
 <module-option name="hashEncoding" value="hex"/>
 <module-option name="principalsQuery" value="select PASSWORD from USERID where ID=?"/>
 <module-option name="rolesQuery" value="select GROUP_ID,'Roles' from USERID_USERGROUP where ID=?"/>
 <module-option name="unauthenticatedIdentity" value="anonymous"/>
 </login-module>
 <login-module code="RoleMapping" flag="required">
 <module-option name="rolesProperties" value="file:${jboss.server.config.dir}/imixsrealm.properties"/>
 <module-option name="replaceRole" value="false"/>
 </login-module>
 </authentication>
 </security-domain>

Using RunAs Annotations

To allow @runas annotation in EJBs the deployment descriptor ‘jboss-ejb3.xml’ need to be added to the standard descriptor ‘ejb-jar.xml’.

jboss-ejb3.xml:

<?xml version="1.1" encoding="UTF-8"?>
  <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
  xmlns="http://java.sun.com/xml/ns/javaee"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:s="urn:security:1.1"
 xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
 version="3.1" impl-version="2.0">
<assembly-descriptor>
 <s:security>
 <ejb-name>*</ejb-name>
 <!-- other imixsrealm -->
 <s:security-domain>imixsrealm</s:security-domain>
 <s:missing-method-permissions-deny-access>false</s:missing-method-permissions-deny-access>
 </s:security>
 </assembly-descriptor>
</jboss:ejb-jar>

Debug Security Problems

If something went wrong you can set the log level for org.jbos.security to TRACE. Stop the server, add the following log category into the standalone.xml file and restart the server:

 <logger category="org.jboss.security">
 <level name="TRACE"/>
 </logger>

 

WebServices – RestEasy Configuration

Using RestServices makes it necessary to change things in the web.xml file because Jersey (used by GlassFish) and RestEasy (used by Wildfly) have different configurations.
In GlassFish V3 a RestService configuration for Jersey looks typically like this:

<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
 <servlet>
 <servlet-name>ImixsRestService</servlet-name>
 <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
 <init-param>
 <param-name>com.sun.jersey.config.property.packages</param-name>
 <param-value>org.imixs.workflow.jaxrs</param-value>
 </init-param>
 <load-on-startup>1</load-on-startup>
 </servlet>

In WildFly you need to chage the configuration like this:

<context-param>
 <param-name>resteasy.scan</param-name>
 <param-value>true</param-value>
 </context-param>
 <context-param>
 <param-name>resteasy.servlet.mapping.prefix</param-name>
 <param-value>/rest</param-value>
 </context-param>
 <listener>
 <listener-class>
 org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
 </listener-class>
 </listener>
 <servlet>
 <servlet-name>ImixsRestService</servlet-name>
 <servlet-class>
 org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
 </servlet-class>
 </servlet>

An useful short example about resteasy you can find here
http://www.mkyong.com/webservices/jax-rs/resteasy-hello-world-example/

 

Mail Configuration

In different to GlassFish, WildFly needs a valid mail configuration if a mail resource is bound to the deployed configuration. So before your can test a application with a mail resource you need to create it!.

Using mail sessions makes it necessary to know some details about JNDI Resource names. In GlassFish you can configure a jndi resource with any name you choose.

For example: mail/org.imixs.workflow.mail
The configuration in your ejb-jar.xml or web.xml file looks than like this:

<!-- Mail Configuration -->
<env-entry>
<description> Mail Plugin Session name</description>
<env-entry-name>IMIXS_MAIL_SESSION</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>mail/org.imixs.workflow.mail</env-entry-value>
</env-entry>
<resource-ref>
<res-ref-name>mail/org.imixs.workflow.mail</res-ref-name>
<res-type>javax.mail.Session</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

In WildFly the name ‘mail/org.imixs.workflow.mail’ is not allowed to be used as a JNDI resource name. You allways have to start
with the prafix ‘java:/’ or ‘java:jboss:/’. This means your jndi mail resource name would be ‘java:/mail/org.imixs.workflow.mail’
And so you also need to change the res-ref-name tag in your ejb-jar.xml or web.xml like this:

<!-- Mail Configuration -->
<env-entry>
<description> Mail Plugin Session name</description>
<env-entry-name>IMIXS_MAIL_SESSION</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>mail/org.imixs.workflow.mail</env-entry-value>
</env-entry>
<resource-ref>
<res-ref-name>java:/mail/org.imixs.workflow.mail</res-ref-name>
<res-type>javax.mail.Session</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

In general Wildfly use always the java:/ prfix in jndi names. Se be careful about this small change in the naming.

beans.xml

If you extend the EJB Module with custom EJBs you need to take care adding the beans.xml file
into the /src/main/resources/META-INF/ folder. The file can be an empty xml file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
 http://java.sun.com/xml/ns/javaee 
 http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

Configuration of mail-session in standalone.xml

To add a mail resource to WildFly you can modify the standalone.xml file. Add the new mail resource into the tag entry ‘<subsystem xmlns=”urn:jboss:domain:mail:2.0″>’

<subsystem xmlns="urn:jboss:domain:mail:2.0">
 <mail-session name="default" jndi-name="java:jboss/mail/Default">
 <smtp-server outbound-socket-binding-ref="mail-smtp"/>
 </mail-session>

<mail-session name="java:/mail/org.imixs.workflow.mail" jndi-name="java:/mail/org.imixs.workflow.mail" debug="true">
     <smtp-server outbound-socket-binding-ref="mail-smtp"/>
 </mail-session>
</subsystem>

It’s important to define the smtp-server outbound-socket-binding-ref which is defined in the section ‘socket-binding-group’. See the following example:

 <outbound-socket-binding name="mail-smtp">
 <remote-destination host="localhost" port="25"/>
 </outbound-socket-binding>

8 Replies to “Migrate from GlassFish to WildFly”

  1. Hi,
    Great article “Migrate from GlassFish to WildFly”, It worked for me, after a long struggle with migration I finally found this blog which worked from migrating Glassfish 4.1 to WildFly 9.1.
    Thanks and appreciate your post.

  2. I have some JARs, normally I copy them (with a small dist.sh script in every project) to ${GF_HOME}/domain1/lib/ restart the server (only GF) and that is all. But nothing like that works in WilfFly, or does it?

  3. Hello,
    I try to migrate an application from GF to WF 10, everything seems to work exept autentification: after login I am redirecting to http: // mysite / j_security_check but if i reload site it’s ok
    any idea ??

  4. Hi,

    I’m having issue migrating from Glassfish 3 to JBoss6.4 . In Glassfish I’m using a custom keyfile, what is the equivalent in JBoss?
    (I only have an admin user in that keyfile for testing purpose)

    If there is no equivalent in JBoss, what’s the best approach if I just wanna create an Admin application user?

    I tried configure JBoss security domain, and I followed every step, but still failed to pass the authentication.

    Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.