Modularity and plug-ability features in Servlet 3.0 specification with Tomcat 9

Modularity and plug-ability features in Servlet 3.0 specification is also called web fragments. The JSR 315 (Java Servlet 3.0 specification) is already 9 years old. The final release dates back to december 10, 2009.
https://jcp.org/en/jsr/detail?id=315
Web fragments are one of the main features of this JSR.
A web fragment is an XML file named web-fragment.xml and located inside the META-INF folder of a jar library.
The root element of this file must be :

<web-fragment>

Web fragments are XML files that will have part of the configurations of a web.xml file.

Here is a short and quick demonstration of it. First, create a web app project with the help of the maven-archetype-webapp archetype.

Here is the content of the web.xml of this first project :

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
</web-app>

Now create a second project with the help of the maven-archetype-quickstart archetype. Add a resources folder under src/main and then create a META-INF folder under that resources folder. Finally add a new file called web-fragment.xml to that META-INF folder with the following content :

<?xml version="1.0" encoding="UTF-8"?>
<web-fragment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
              id="WebAppFragment_ID" version="3.0">
    <name>authentication-fragment</name>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Client</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>client</role-name>
        </auth-constraint>
    </security-constraint>

    <security-role>
        <role-name>client</role-name>
    </security-role>

    <login-config>
        <auth-method>FORM</auth-method>
        <realm-name>Client</realm-name>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/login-error.jsp</form-error-page>
        </form-login-config>
    </login-config>

    <error-page>
        <error-code>404</error-code>
        <location>/home.jsp</location>
    </error-page>

</web-fragment>

Add this second project as a dependency in the first project :

...
	<dependency>
			<groupId>com.celinio</groupId>
			<artifactId>secondproject</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
...

Now if we deploy the artefact mainproject.war to a web server such as Tomcat for instance, the following web.xml will be produced :

15-Dec-2018 18:42:12.960 INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive [E:\devJava\apache-tomcat-9.0.13\webapps\mainproject.war]
15-Dec-2018 18:42:13.194 INFO [main] org.apache.catalina.startup.ContextConfig.webConfig web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>  <display-name>Archetype Created Web Application</display-name>




  <servlet>
    <servlet-name>default</servlet-name>
    <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
    <init-param>
      <param-name>listings</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>debug</param-name>
      <param-value>0</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet>
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    <init-param>
      <param-name>fork</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>xpoweredBy</param-name>
      <param-value>false</param-value>
    </init-param>
    <load-on-startup>3</load-on-startup>
  </servlet>

...
<security-constraint>
    <web-resource-collection>
      <web-resource-name>Client</web-resource-name>
      <url-pattern>%2F*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>client</role-name>
    </auth-constraint>
    <user-data-constraint>
      <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
  </security-constraint>

  <login-config>
    <auth-method>FORM</auth-method>
    <realm-name>Client</realm-name>
    <form-login-config>
      <form-login-page>/login.jsp</form-login-page>
      <form-error-page>/login-error.jsp</form-error-page>
    </form-login-config>
  </login-config>

  <security-role>
    <role-name>client</role-name>
  </security-role>



</web-app>
With Tomcat 9, to view the content of the generated web.xml, it is necessary to add the logEffectiveWebXml attribute to the context tag in the context.xml file located under the conf folder and set it to true :
<?xml version="1.0" encoding="UTF-8"?>
<!-- The contents of this file will be loaded for each web application -->
<Context  logEffectiveWebXml="true">

    <!-- Default set of monitored resources. If one of these changes, the    -->
    <!-- web application will be reloaded.                                   -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>

    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <!--
    <Manager pathname="" />
    -->
</Context>
During the deployment, the web server scans and treats the various web fragments that it might find. It will concatenate all the fragments to the main web.xml file. This is a simple demonstration. You might be wondering what might happen if there is more than one web fragment file and more precisely in which order will they be added to the generated web.xml. Well, to deal with that, the absolute-ordering tag was added :
<web-app>
...
<absolute-ordering>
   <name>MyFirstFragment</name>
   <name>MySecondFragment</name>
</absolute-ordering>
...
</web-app>

Finally, the web fragments can also contain ordering themselves with the use of the ordering tag :
<web-fragment>
<name>MyFirstFragment</name>
...
<ordering>
   <before>
   		<name>MySecondFragment</name>
   </before>
</ordering>
...
</web-app>

The code of this small demonstration is on my github account :
https://github.com/longbeach/webfragments.git


JMS with Weblogic Server and EJB MDB

Here is a complete and short example of asynchronous development using JMS and a Message-Driven Bean (MDB).
First the procedure to configure inside Weblogic Server a JMS server in order to create a queue, then the code for the producer/sender of a message to the queue and then the code for a consumer (MDB).

1) Weblogic configuration
a) Create the JMS server

JMS_Weblogic1

JMS_Weblogic2

JMS_Weblogic3

JMS_Weblogic4

b) Create a JMS module
JMS_Weblogic5

JMS_Weblogic6

JMS_Weblogic7

JMS_Weblogic8

JMS_Weblogic9

JMS_Weblogic10

JMS_Weblogic11

JMS_Weblogic12

c) Create a destination (queue or topic)

JMS_Weblogic13

JMS_Weblogic14

JMS_Weblogic15

JMS_Weblogic16

d) Create a connection factory

JMS_Weblogic17

JMS_Weblogic18

JMS_Weblogic19

2) Create a producer

For the producer, I got strongly inspired by the code found in this blog. This is a clean example of a producer/sender so no need to reinvent the wheel here.

import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class JMSProducer {

	private static InitialContext initialContext = null;
	private static QueueConnectionFactory queueConnectionFactory = null;
	private static QueueConnection queueConnection = null;
	private static QueueSession queueSession = null;
	private static Queue queue = null;
	private static QueueSender queueSender = null;
	private static TextMessage textMessage = null;
	private static final String CONNECTIONFACTORY_NAME = "ConnectionFactory-Test";
	private static final String QUEUE_NAME = "jms/QueueTest";

	public JMSProducer() {
		super();
	}

	public static void sendMessageToDestination(String messageText) {
		// create InitialContext
		Hashtable properties = new Hashtable();
		properties.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
		properties.put(Context.PROVIDER_URL, "t3://localhost:7001");
		properties.put(Context.SECURITY_PRINCIPAL, "weblogic");
		properties.put(Context.SECURITY_CREDENTIALS, "weblogic1");
		try {
			initialContext = new InitialContext(properties);
		} catch (NamingException ne) {
			ne.printStackTrace(System.err);
		}
		System.out.println("InitialContext : " + initialContext.toString());
		// create QueueConnectionFactory
		try {
			queueConnectionFactory = (QueueConnectionFactory) initialContext.lookup(CONNECTIONFACTORY_NAME);
		} catch (NamingException ne) {
			ne.printStackTrace(System.err);
		}

		System.out.println("QueueConnectionFactory : " + queueConnectionFactory.toString());
		// create QueueConnection
		try {
			queueConnection = queueConnectionFactory.createQueueConnection();
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("QueueConnection : " + queueConnection.toString());
		// create QueueSession
		try {
			queueSession = queueConnection.createQueueSession(false, 0);
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("QueueSession : " + queueSession.toString());
		// lookup Queue
		try {
			queue = (Queue) initialContext.lookup(QUEUE_NAME);
		} catch (NamingException ne) {
			ne.printStackTrace(System.err);
		}

		System.out.println("Queue : " + queue.toString());
		// create QueueSender
		try {
			queueSender = queueSession.createSender(queue);
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("QueueSender : " + queueSender.toString());
		// create TextMessage
		try {
			textMessage = queueSession.createTextMessage();
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("TextMessage : " + textMessage.toString());
		try {
			textMessage.setText(messageText);
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("TextMessage : " + textMessage.toString());
		// send message
		try {
			queueSender.send(textMessage);
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("Message sent.");
		// clean up
		try {
			textMessage = null;
			queueSender.close();
			queueSender = null;
			queue = null;
			queueSession.close();
			queueSession = null;
			queueConnection.close();
			queueConnection = null;
			queueConnectionFactory = null;
			initialContext = null;
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("Cleaned up done.");
	}

	public static void main(String args[]) {
		sendMessageToDestination("test");
	}
}

3) Create a consumer

This MDB consumer just prints out something in the log when it consumes the message in the queue.
The lifecycle methods are empty but they could be used to clean up resources for instance.

import javax.ejb.ActivationConfigProperty;
import javax.ejb.EJBException;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@MessageDriven(mappedName = "jms/QueueTest", activationConfig = {
		@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
		@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") })
public class TestJMSSABean implements MessageDrivenBean, MessageListener {

	/** The Constant LOGGER. */
	protected static final Logger LOGGER = LoggerFactory.getLogger(TestJMSSABean.class);

	public TestJMSSABean() {
	}

	@Override
	public void onMessage(Message message) {
		try {
			if (message instanceof TextMessage) {
				System.out.println(((TextMessage) message).getText());
				LOGGER.trace("***************** : " + ((TextMessage) message).getText());
			} else {
				System.out.println(message.getJMSMessageID());
				LOGGER.trace("***************** : " + message.getJMSMessageID());
			}
		} catch (JMSException ex) {
			LOGGER.trace("***************** ERROR : " + ex.getMessage());
		}
	}

	@Override
	public void ejbRemove() throws EJBException {
		// TODO Auto-generated method stub
	}

	@Override
	public void setMessageDrivenContext(MessageDrivenContext arg0) throws EJBException {
		// TODO Auto-generated method stub
	}
}

Prevent Weblogic Server from wrapping data types

By default, Weblogic Server wraps data types such as Struct, Blob, Array, Clob, etc.

For instance, oracle.sql.STRUCT becomes weblogic.jdbc.wrapper.Struct_oracle_sql_STRUCT.

That can become a problem if for instance you’re expecting a data type :


oracle.sql.STRUCT objSTRUCT = (oracle.sql.STRUCT) callableStatement.getObject(2);

This would raise the following error :


java.lang.ClassCastException: weblogic.jdbc.wrapper.Struct_oracle_sql_STRUCT

To avoid it, one can simply disable that wrapping in the Weblogic administration console :

Go to Services > Data sources > Select your datasource > “Connection pools” tab > Advanced  :

uncheck “Wrap data types”

WrapDataTypes_WeblogicWrapDataTypes2

Note : Weblogic Server version used is 10.3.5

Unit testing EJBs with PowerMockito

I had to find a way to test a method from a stateful session bean (EJB PersonSABean implements PersonSF) defined in a service layer that calls another method from another stateful session bean (EJB HouseSFBean implements HouseSF) defined in a business layer.

To call that method from EJB HouseSFBean, the EJB PersonSABean needs to perform a lookup to get a reference to the EJB HouseSF. In that case, a static method is often created inside a static or final class. For instance :

public final class EjbUtil {
public static <T> T lookup(final Class<T> clazz) throws SomeException {
 InitialContext context = null;

try {
 context = new InitialContext(new PropertiesLoader().loadProperties("myProperties.txt"));
}
 return clazz.cast(context.lookup(name));
} catch (NamingException e) {
 throw new SomeException(e.getMessage());
} finally {
...
}

...

}
@TransactionManagement(TransactionManagementType.CONTAINER)
@Stateless(name = "PersonSA")
@Remote(value = { PersonSA.class })
@Interceptors(HandlerExceptionInterceptorSA.class)
public class PersonSABean extends BasicSABean implements PersonSA {
 ...
 private HouseSF houseSF;

 public HouseSF getHouseSF() {
    houseSF = EjbUtil.lookup(PersonSF.class, "ejb.company.project.application.HouseSF");
    return houseSF;
 }
}

But unit tests, unlike integration tests, are meant to test a specific method (or class). They are not meant to test the methods that it calls. So in my case, i do not need  to make – and should not make – a JNDI lookup to get a reference to the EJB HouseSF . So I have to mockup the EjbUtil.lookup(…)  static method.

Fortunately, PowerMockito can mock a static method so the solution is to use both Mockito and PowerMockito :

@RunWith(PowerMockRunner.class)
@PrepareForTest(EjbUtil.class)

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyListOf;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.stub;

import java.util.ArrayList;
import java.util.List;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@Category(UnitTest.class)
@RunWith(PowerMockRunner.class)
@PrepareForTest(EjbUtil.class)
public class PersonSABeanTest {

@Mock
private HouseSF houseSF;

private PersonSABean personSABean;

@Before
public void setUp() throws Exception {
  MockitoAnnotations.initMocks(this);
  personSABean = new PersonSABean();
  personSABean.setHouseSF(houseSF);
  PowerMockito.mockStatic(EjbUtil.class);
}

@Test
public void testSomeMethod() throws SomeBusinessException {
  ...
  SomeDTO someDTO = new SomeDTO();
  stub(houseSF.someMethod(anyListOf(A.class), anyListOf(BDTO.class), any(CDTO.class), anyInt())).toReturn(someDTO);
  Mockito.when(EjbUtil.lookup(anyString(), Mockito.eq(HouseSF.class), anyString())).thenReturn(houseSF);
  ...
}

Link :
https://code.google.com/p/powermock/wiki/MockitoUsage13


			
				
			
			

[JPA 2] Criteria API and MetaModel

I want to mention the Criteria API, a very cool API which in my opinion is not used as much as it should be. The developers who implement the specification (JSR 317: Java Persistence 2.0) do an impressive work. Thanks to them we have an API that makes it possible to write type safe queries in an object oriented way.
Usually Java developers write queries using JPQL or they write native queries. The fact is that the API Criteria has a (small) learning curve : you have to explore the API and study some basic queries examples before writing your own queries. The first time you use it, it does not seem as intuitive as JPQL.

The Criteria API is particularly convenient when writing queries which do not have a static where clause. For instance in the case of a web page where the user can make a research based on optional criterias. Then the generated query is not always the same.

The Criteria API has its advantages and its disadvantages : it produces typesafe queries that can be checked at compile time but on the other hand queries can be a bit hard to read (apparently unlike QueryDSL or EasyCriteria).
Another advantage is that it can help to avoid SQL injection since the user input is validated or escaped by the JDBC driver (which is not the case with native queries).

To create typesafe queries, one uses the canonical metamodel class associated to an entity (an idea originally proposed by Gavin King, as far as i know). A possible definition of a metamodel class could be that one : it is a class that provides meta information about a managed entity. By default, it has the same name as the entity plus an underscore. For instance if an entity is called Employee then the metamodel class is called Employee_. It is annotated with the annotation javax.persistence.StaticMetamodel.
Fortunately you do not have to write them, you can generate them using an annotation processor, through Eclipse or a Maven plugin for instance.
I chose to generate the metamodel classes with the help of the Hibernate Metamodel Generator (an annotation processor) and the maven-processor-plugin maven plugin, at each build so that they are updated whenever the entities are modified. It is a good way to keep the metamodel classes up to date.

<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>2.0.5</version>
<dependencies>
<!-- Annotation processor to generate the JPA 2.0 metamodel classes for typesafe criteria queries -->
  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-jpamodelgen</artifactId>
    <version>1.2.0.Final</version>
  </dependency>
</dependencies>
<executions>
  <execution>
    <id>process</id>
    <goals>
      <goal>process</goal>
    </goals>
    <phase>generate-sources</phase>
    <configuration>
      <outputDirectory>${project.basedir}/src/main/.metamodel/</outputDirectory>
      <processors>
        <processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
      </processors>
    </configuration>
  </execution>
</executions>
</plugin>

<!--  add sources (classes generated inside the .metamodel folder) to the build -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
  <execution>
    <id>add-source</id>
    <phase>generate-sources</phase>
    <goals>
      <goal>add-source</goal>
    </goals>
    <configuration>
      <sources>
        <source>${basedir}/src/main/.metamodel</source>
      </sources>
    </configuration>
  </execution>
</executions>
</plugin>

And here is the kind of dynamic query one can create :
Continue reading

My book on EJB 3 is now on sale

I received an email from the editor informing me that the book is now printed and will be available in bookstores next week (from July 5th, 2010).

It is already available for sale on Amazon and ENI.

An online version is also available.

Here is the cover of the book :

SO3EJB_max

No direct access for JSP under WEB-INF

I have been asked several times in the past whether files under WEB-INF can be accessed or not.
It is indeed somewhat confusing. The answer is YES and NO.

You cannot access them directly.

For instance the following URL would give a 404 error :
http://localhost:8085/myWebApp/WEB-INF/test.jsp

But you can access test.jsp indirectly.
For instance the following JSP, callTest.jsp, contains code that includes a call to the somewhat protected JSP test.jsp :

<%@ include file="WEB-INF/test.jsp" %>

The URL to call the JSP is :
http://localhost:8085/myWebApp/callTest.jsp