SeedStack on WebSphere

IBM WebSphere Application Server (WAS) is a complex Web application server that can pose some challenges to developers. The goal of this guide is to aggregate useful information about deploying SeedStack application on WAS successfully.

This guide applies to WAS 8.0 and above.

Minimum version

SeedStack requires at least Servlet level 3.0 which is available starting from WAS 8.0. However since SeedStack requires Java SE 8, it is recommended to use the last release of WAS 8.5.5.

Classloader

SeedStack is not JEE-based so it provides support for various Java standards (JSR), but not necessarily aligned with JEE versions. For that reason the classloader setting in WAS should be set to Parent last. This allows SeedStack to use newer versions of Java standards than the ones mandated by the server JEE level.

Bean validation

In recent versions, SeedStack comes with Bean Validation 2 implemented with Hibernate Validator 6+. If this gives you issues at application startup, you can downgrade to Bean Validation 1.1 and Hibernate Validator 5 by using the following dependency management:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.4.3.Final</version>
        </dependency>
    </dependencies>
</dependencyManagement>

Web.xml

SeedStack (starting with version 15.11.1) does not necessitate a web.xml file to be present under WEB-INF. However if you want to use injection and interception on annotation-based servlet, filter and listener classes, you must disable container scanning. This is done with an almost empty web.xml file, setting the metadata-complete attribute to true:

<web-app 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/web-app_3_0.xsd"
         version="3.0"
         metadata-complete="true">
</web-app>

JNDI

To do a successful JNDI lookup in SeedStack, you must follow this procedure.

Declare the JNDI reference in the web.xml file, creating it if necessary (see above). The following example is for a JDBC datasource:

<web-app 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/web-app_3_0.xsd"
         version="3.0"
         metadata-complete="true">
    <resource-ref>
        <description>My datasource</description>
        <res-ref-name>jdbc/TestDB</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
</web-app> 

For other types of JNDI resources, just change the class name in res-type to the correct type. You can change res-auth to Application if the application should handle authentication to the resource.

Declare the JNDI binding in the IBM-specific ibm-web-bnd.xml file under WEB-INF:

<?xml version="1.0" encoding="UTF-8"?>
<web-bnd 
    xmlns="http://websphere.ibm.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-bnd_1_0.xsd"
    version="1.0">
        <resource-ref name="jdbc/TestDB" binding-name="jdbc/TestDB" />
</web-bnd>

You can choose to alter the JNDI name seen from the application by changing the name attribute.

Refer to the JNDI name bound in the previous step in SeedStack configuration:

jdbc:
  datasources:
    myDatasource:
      jndiName: jdbc/TestDB

Or directly in code with an annotation:

public class SomeClass {
    @Resource(name = "jdbc/TestDB")
    private DataSource myDatasource;
}

Or through direct lookup:

public class SomeClass {
    @Inject
    private Context jndiContext;
 
    public void someMethod(){
       DataSource myDatasource = (DataSource) jndiContext.lookup("jdbc/TestDB");
    }
}

For more information, read the documentation about JNDI.

JPA

If you want to use a JPA specification version beyond what your WebSphere server support, you can do so by setting up a PersistenceProviderResolver that forces your more recent provider to be the only JPA provider. Here is the code of a SeedInitializer that does this task:

package org.generated.project.infrastructure.jpa;

import java.util.Collections;
import java.util.List;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceProviderResolver;
import javax.persistence.spi.PersistenceProviderResolverHolder;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.seedstack.coffig.Coffig;
import org.seedstack.seed.spi.SeedInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HibernatePersistenceProviderResolver implements PersistenceProviderResolver, SeedInitializer {
    private static final Logger LOGGER = LoggerFactory.getLogger(HibernatePersistenceProviderResolver.class);
    private final PersistenceProvider persistenceProvider = new HibernatePersistenceProvider();

    @Override
    public void afterInitialization() {
        PersistenceProviderResolverHolder.setPersistenceProviderResolver(this);
        LOGGER.info("Registered Hibernate as unique JPA provider");
    }

    @Override
    public List<PersistenceProvider> getPersistenceProviders() {
        return Collections.singletonList(persistenceProvider);
    }

    @Override
    public void clearCachedProviders() {
        // no-op
    }

    @Override
    public void beforeInitialization() {
        // no-op
    }

    @Override
    public void onInitialization(Coffig configuration) {
        // no-op
    }

    @Override
    public void afterRefresh() {
        // no-op
    }

    @Override
    public void onClose() {
        // no-op
    }
}

SeedStack initializers are discovered by the Java Service Loader mechanism. To be discovered the class full qualified name must be written on its own line in a file named META-INF/services/org.seedstack.seed.spi.SeedInitializer:

org.generated.project.infrastructure.jpa.HibernatePersistenceProviderResolver

On this page


Edit