Embeded Glassfish for Integration Tests

Sun Glassfish server can be run in embeded mode, very useful for automated integration tests. Here’s how:

Maven Dependencies:

<dependency>
  <groupId>org.glassfish.distributions</groupId>
  <artifactId>web-all</artifactId>
  <version>10.0-build-20080430</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.glassfish.embedded</groupId>
  <artifactId>gf-embedded-api</artifactId>
  <version>1.0-alpha-4</version>
  <scope>test</scope>
</dependency>

If you are not using maven then add the above libs to you classpath. Getting the server started in simple

final URI APP_URI= UriBuilder.fromUri("http://localhost/").port(8888).path("myapp").build();
GlassFish server= new GlassFish(BASE_URI.getPort());
ScatteredWar war = new ScatteredWar(APP_URI.getRawPath(),
   new File("src/main/webapp"),
   new File("src/main/webapp/WEB-INF/web.xml"),
   Collections.singleton(new File("target/classes").toURI().toURL()));
server.deploy(war);

You can then use any HTTP Client to send a HTTP Request to the server on a defined port. For automated integration tests use TestNG “dependsOnMethods” feature to ensure that the server was started before executing you integration test group(s). You can then have anther test which depends on your integration test group(s) to ensure that the server is stopped when tests have finished.

You can stop the server with server.stop(). Note: If you are using Maven then using cargo to bring up the server may be more advisable.

Creating custom layouts in JBoss Portal

The layout of a portlet is handled by a set of JSP in the portal-core web-app which is part of the jboss-portal.sar. In the web-inf direcotry have a look at portal-layouts.xml to see how various layouts are configured. The following is a snippet (self explainatory):

<layouts>
<layout>
  <name>rbs-1column</name>
  <uri>/layouts/mylayout/index.jsp</uri>
  <uri state="maximized">/layouts/mylayout/maximized.jsp</uri>
  <regions>
    <region name="regionBody"/>
  </regions>
</layout>
</layouts>

You can make changes to these JSPs and the portal-layouts.xml. Alternatively (recommended), create you own theme in a separate web app (war file) and change the following config in jboss-portal.sar/META-INF/jboss-service.xml. You need to change the fillowing lines:

  • Change layout context path: <attribute name="TargetContextPath">/mylayoutapp</attribute>
  • Change path to header jsp: <attribute name="HeaderPath">/WEB-INF/jsp/myheader.jsp</attribute>
  • Change path to tabs (navigation) jsp: <attribute name="TabsPath">/WEB-INF/jsp/mynavigation.jsp</attribute>

The new war file will need to have access to the to portal lib tag-libs. These can be found at jboss-portal.sar/portal-core.war/WEB-INF.  Your layout JSP specified as “url” in the portal-layouts.xml will need to include the following directives:

  • In the html header: <p:theme themeName=”mytheme”/>, <p:headerContent/>.  See http://java.dzone.com/articles/jboss-portal for a guide on creating custom themes.
  • In the body: <p:region regionName=’regionBody’ regionID=’regionBody’ />. This will need to be added for all the regions defined in the portal-layout.xml for this particular layout.

Note: Theme and layouts can be specified in the portal page deployment descriptor (see property theme.id and layout.id)

Controlling JBoss Deployments Using MBeans

JBoss allows you to programmatically control deployments using the MBean interface. Note: the same can be done using the JMX Console and Twiddle.

Approach 1: Copy the app to deploy folder and temporarily turn on hot-deployment scanner. This is not recommended for production since the deploy folder may contain other changes you may not have wanted deployed.

The JNDI name for the Deployment Scanner MBean is jboss.deployment:type=DeploymentScanner,flavor=URL. You can then use the following code to get a reference to the scanner. Note: this code will only work inside the container (you can initialise the JDNI context a performa  lookup if you want the code to run outside the container):

URLDeploymentScannerMBean deploymentScanner = 
   (URLDeploymentScannerMBean) MBeanProxyExt.create(
      URLDeploymentScannerMBean.class, "jboss.deployment:type=DeploymentScanner,flavor=URL",
      MBeanServerLocator.locateJBoss());

You can then deploymentScanner.stop() and deploymentScanner.start(). To determine if the scanner is already started you can check for it’s scannerMBean.getState() to be ServiceMBean.STARTED or ServiceMBean.STARTING

Approach 2: You can use the main deployer to deploy the app specifing the URL to it’s location. To obtain a reference to the deployer in the container:

MainDeployerMBean mainDeployer = (MainDeployerMBean) MBeanProxyExt.create(
   MainDeployerMBean.class, "jboss.system:service=MainDeployer",
   MBeanServerLocator.locateJBoss());

You can then deploy the app:

String webappUrl = "file:///home/username/apps/myapp.war";
if (deployerMBean.isDeployed(webappUrl)) {
   deployerMBean.redeploy(webappUrl);
} else {
   deployerMBean.deploy(webappUrl);
}

JBoss Source Code

A good resource for JBoss related examples and source code is at http://anonsvn.jboss.org

To see exactly what 3rd party libraries a particular version of JBoss was developed with have a look at build-thirdparty.xml in the source code (e.g. http://anonsvn.jboss.org/repos/portal/tags/Enterprise_Portal_Platform_4_3_GA_CP03/build/build-thirdparty.xml)