Friday, February 25, 2011

Precompile JSP with Maven 2

There are situations where JDK is banned in production and only JRE allowed for use. In this case if you are using JSP there is only one option to use - precompile JSP. Here is example how to achieve that. Nothing very special, but I guess this can save some time and effort for somebody )

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jspc-maven-plugin</artifactId>
<executions>
<execution>
<id>jspc</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>${basedir}/target/jspweb.xml</webXml>
<warSourceExcludes>**/*.jsp</warSourceExcludes>
</configuration>
</plugin>
WarSourceExcludes will not package original JSPs - really makes no sence since they are just classes and appropriate servlet mappins in web.xml now.

Saturday, February 19, 2011

Mock JNDI in jUnit

JNDI is very useful technology. But... not everywhere. If there is the need to deploy your application on variety of different environments, for example databases with sensitive data and you are not a person who is suitable to deploy application for a bunch of reasons - segregation of concepts, separate production team, etc - JNDI is what you need. If you are with JNDI, only thing you have to provide is JNDI names with example config, so that person responsible for deployment could figure out how to deal with it. Just imagine the mess when you need to deploy war file for ~10 different Oracle databases and the same number of WebSphere MQ queues without JNDI. Think for 1 min :)

But, in development is not so pleasant to have a deal with JNDI, since container required in this case to perform actual lookup of resources. From the other point of view not all so bad, since there is a way in 10 lines of code to mock required JNDI datasource. In fact it could be any other resource, but data source seems to be the most popular.

Key point here is the use of the calss from SpringSource -
org.springframework.mock.jndi.SimpleNamingContextBuilder

Here is the complete example how to use it -

import com.blogspot.ostas.cxf.SimpleDao;
import oracle.jdbc.pool.OracleDataSource;
import org.apache.log4j.Logger;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.naming.NamingException;
import java.sql.SQLException;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/WEB-INF/dataAccess-applicationContext.xml"})
public class DaoTestCase{
static Logger logger = Logger.getLogger(DaoTestCase.class.getName());
@BeforeClass
public static void setUp(){
OracleDataSource ods = null;
try {
ods = new OracleDataSource();
} catch (SQLException e) {
logger.error(e);
}
ods.setURL("jdbc:oracle:thin:@127.0.0.1:1521/orcldb");
ods.setUser("*");
ods.setPassword("*");
SimpleNamingContextBuilder builder = null;
try {
builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
builder.bind("java:comp/env/jdbc/db",ods);
} catch (NamingException e) {
logger.error(e);
}
}
@Autowired
SimpleDao simpleDao;
@Test
public void testInjectBean() throws Exception
{
logger.debug("Bean : >>> " + simpleDao);
assertNotNull(simpleDao);
}
@Test
public void testDBconnection() throws Exception{
assertEquals(simpleDao.getNumber(),1);
}
}

As you can see from this code, actual mock is just

SimpleNamingContextBuilder builder = null;
try {
builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
builder.bind("java:comp/env/jdbc/db",ods);
} catch (NamingException e) {
logger.error(e);
}
ods - just plain DataSource. From Spring point jdbc/db looks llike this -

<bean id="dataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/db</value>
</property>
</bean>

The last thing I have to mention here is Maven2 dependency for use SimpleNamingContextBuilder class -

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.0.3.RELEASE</version>
<scope>test</scope>
</dependency>