Tag Archives: tomcat

Replacing web.xml with Java based Configuration for Servlet 3.x Webapplications

With the Servlet 3.x API as part of JEE 6 come with the possibility to configure a java web application by writing a java class instead of having a web.xml file inside the WEB-INF folder. My sample apache cxf project has a web.xml with a spring configuration listener and a cxf servlet mapping. I use jetty for integration tests inside maven builds and tomcat as application server for deployment and running the web application. The web service sample use Spring 3.1 and Apache CXF 2.6.2.

I migrated my old web project with just a few steps:

Maven Settings

Step 1: Integrate latest Spring Web API

The Spring 3.1 web project contains the SpringServletContainerInitializer class which will be automatically invoked by a servlet 3.x container:

	
		2.6.2
		3.1.2.RELEASE
	
		
			javax
			javaee-api
			6.0
			provided
		
		
			org.apache.cxf
			cxf-rt-frontend-jaxws
			${cxf.version}
		
		
			org.apache.cxf
			cxf-rt-transports-http
			${cxf.version}
		

		
		
			org.apache.cxf
			cxf-rt-transports-http-jetty
			${cxf.version}
		
		
			org.eclipse.jetty
			jetty-webapp
			8.1.1.v20120215
		
		
			junit
			junit
			4.10
			jar
			compile
		
		
			org.springframework
			spring-test
			${spring.framework.version}
			jar
			compile
		
		
			org.springframework
			spring-core
			${spring.framework.version}
			jar
			compile
		
		
			org.springframework
			spring-beans
			${spring.framework.version}
		
		
			org.springframework
			spring-web
			${spring.framework.version}
		

Step 2: Update build plugin for jetty to use servlet 3.x api

The Jetty 8.x supports Servlet 3.x api to support bootstrapping and java based configurations and is used by the jetty plugin:

			
				org.mortbay.jetty
				jetty-maven-plugin
				8.1.5.v20120716
				
					10
					
						/${project.artifactId}
					
					true
					foo
					9999
					
						
							9090
							60000
						
					
				
				
					
						start-jetty
						pre-integration-test
						
							run
						
						
							0
							true
						
					
					
						stop-jetty
						post-integration-test
						
							stop
						
					
				
			

Step 3: Configure Maven War Plugin to ignore web.xml

The maven war plugin throws otherwise a exception if it does not found the web.xml file:

			
				org.apache.maven.plugins
				maven-war-plugin
				2.2
				
					src/main/webapp
					${project.artifactId}
					false
					
					
						
				
			

 

Java Configuration

Step 4: Write Configuration file

Write a class that implement the WebApplicationInitializer interface from Spring Web and override the onStartup Method. Inside that you have to setup spring application context and map the servlet classes to url patterns:

package demo.spring.cfg;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.XmlWebApplicationContext;

public class WebAppInitializer implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext container) throws ServletException {
		XmlWebApplicationContext rootContext = new XmlWebApplicationContext();
		rootContext.setConfigLocations(new String[] { "classpath*:applicationContext.xml" });
		container.addListener(new ContextLoaderListener(rootContext));

		ServletRegistration.Dynamic dispatcher = container.addServlet("CXFServlet", CXFServlet.class);
		dispatcher.addMapping("/*");
	}
}

Step 5: Delete web.xml

Delete inside WEB-INF folder the web.xml file and use the mvn clean command to remove it from target folder.

Step 6: Testing

run mvn package to build the war file in your project. Download and extract tomcat 7.x for testing your war file. Put the war file in the webapps folder and run your server with the startup.bat in the bin folder of tomcat.

Configuring solr, tomcat 7 with mod_jk and apache 2.2

As follow up post to setting up solr i show you how to integrate tomcat into Apache as main web server:

The setup was made under ubuntu 11.10 with the following prerequisites:

  • CATALINA_HOME is /usr/share/tomcat7
  • JAVA_HOME is /usr/lib/jvm/default-java
  • HOSTNAME in my case is ubuntu-vm.localdomain

 

  1. apt-get install libapache2-mod-jk
  2. nano /etc/apache2/workers.properties with the following contents
workers.tomcat_home=/usr/share/tomcat7
workers.java_home=/usr/lib/jvm/default-java
ps=/
worker.list=ajp13
worker.ajp13.port=8009
worker.ajp13.host=localhost
worker.ajp13.type=ajp13
worker.ajp13.lbfactor=1
  1. nano /etc/apache2/mods-available/jk.conf with the following contents

        # Where to find workers.properties
        JkWorkersFile /etc/apache2/workers.properties
        # Where to put jk shared memory
        JkShmFile     /var/log/apache2/mod_jk.shm
        # Where to put jk logs
        JkLogFile     /var/log/apache2/mod_jk.log
        # Set the jk log level [debug/error/info]
        JkLogLevel    info
        # Select the timestamp log format
        JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
        # solr redirect
        JkMount /solr* ajp13

  1. less /etc/apache2/mods-available/jk.load to see the following contents
    1. LoadModule jk_module /usr/lib/apache2/modules/mod_jk.so
  2. run a2enmod jk to see if mod_jk is enabled
    1. Module jk already enabled
  3. less /usr/share/tomcat7/conf/server.xml to see a line like this
    1. <Connector port=”8009″ protocol=”AJP/1.3″ redirectPort=”8443″ />
  4. nano /etc/apache2/sites-available/default and insert a line into the virtualHost:80 section
    1. JKMountCopy On
  5. restart apache2 with service apach2 restart
  6. Open a browser on your client to open http://ubuntu-vm.localdomain/solr/admin/

Installing Solr 3.5 under Tomcat 7

Solr is a open source Enterprise Search Engine. It can be deployed as war file in servlet containers like tomcat or jetty.

This short howto show you run solr with the current Tomcat 7 version:

  1. Download Solr as Zip
  2. Unzip it e.g. in /usr/share/ with folder structure
    1. mv apache-solr-3.5.0.zip /usr/share
    2. cd /usr/share
    3. unzip apache-solr-3.5.0.zip
    4. result is a folder /usr/share/apache-solr-3.5.0
  3. Create a new folder e.g /usr/share/solr as base folder for the configuration
    1. cp -a /usr/share/apache-solr-3.5.0/example/solr /usr/share/solr
    2. cp /usr/share/apache-solr-3.5.0/dist/*.war /usr/share/solr
    3. ln -s /usr/share/solr/apache-solr-3.5.0.war /usr/share/solr.war
    4. mkdir /usr/share/solr/data< for index data/li>
    5. mkdir /usr/share/solr/lib for additional jars
    6. cp /usr/share/apache-solr-3.5.0/dist/apache-solr-velocity-3.5.0.jar /usr/share/solr/lib
    7. cp -a /usr/share/apache-solr-3.5.0/contrib/ /usr/share/solr/
    8. nano /usr/share/solr/conf/solrconfig.xml and change the lib settings
    // ...
      
    
    
      
      
      
      
    
    
    1. chown -R tomcat:tomcat /usr/share/solr if tomcat server runs as user tomcat
  4. Add URIEncoding to tomcat connector settings
    1. nano /usr/share/tomcat7/conf/server.xml
    2. search for the connector on port 8080
    3. add the URIEncoding like this:
    
    
  5. Create a tomcat configuration file for solr (CATALINA_HOME is /usr/share/tomcat7)
    1. cd /usr/share/tomcat7/conf
    2. mkdir Catalina (if not exists)
    3. cd Catalina
    4. mkdir localhost (if not exists)
    5. cd localhost
    6. nano solr.xml
  6. Paste the following configuration and save the file


  

  1. Set properties for tomcat and solr inside /usr/share/tomcat7/bin/setenv.sh
  2. Paste the following configuration and save the file
export JAVA_OPTS="$JAVA_OPTS -Dsolr.solr.home=/usr/share/solr"
export JAVA_OPTS="$JAVA_OPTS -Dsolr.data.dir=/usr/share/solr/data"
export JAVA_OPTS="$JAVA_OPTS -Dsolr.velocity.enabled=true"
export JAVA_HOME="/usr/lib/jvm/default-java"
  1. (Re)start tomcat
    1. /etc/init.d/tomcat7 restart
  2. Open browser and go to http://YOUR_SERVER_HOSTNAME:8080/solr/admin/ assuming that tomcat runs under default port 8080

I use the provided sample xml files to see if import and query functionality works:

  1. cd /usr/share/apache-solr-3.5.0/example/exampledocs
  2. nano post.sh
  3. change the URL parameter to your environment e.g. to URL=http://localhost:8080/solr/update
  4. ./post.sh *.xml
  5. Open the admin ui under http://YOUR_SERVER_HOSTNAME:8080/solr/admin/
  6. click the search button

see my follow up post for Configuring solr, tomcat 7 with mod_jk and apache 2.2

Using Cargo for Maven War Deployments to Tomcat 6.x

JEE based projects with maven build artifacts like war or ear files is the cargo plugin the right choice for automatic deployments during the build process.

First step is to define in the build section of your pom.xml the cargo plugin:


	org.codehaus.cargo
	cargo-maven2-plugin
	1.1.4
	
		
			tomcat6x
			remote
		
		
			runtime
			
				
				${cargo.manager.url}
				${cargo.username}
				${cargo.password}
			
		
		
			remote
			
				
					${project.groupId}
					${project.artifactId}
					war
					
						${project.artifactId}
					
				
			
		
	

Notice the variables with the url and the credentials. The will filled with the used profile section for the build:


	
		tomcat6x_remote
		
			true
		
		
			http://ubuntu-vm.localdomain:8080/manager
			tomcat
			tomcat
		
	
	
		tomcat6x_ide
		
			http://localhost:9999/manager
			tomcat
			tomcat
		
			

The activeByDefault settings marks the remote section as default profile if nothing is set by command line parameters.

With

mvn org.codehaus.cargo:cargo-maven2-plugin:redeploy

you first undeploy the current application and then deploy the new build application to the remote tomcat instance. The command line parameter-Ptomcat6x_ide force maven to use the local tomcat instance for deployments.

mvn -Ptomcat6x_ide org.codehaus.cargo:cargo-maven2-plugin:redeploy

Hudson or Jenkins as continuous integration server can then be setup to use a primary project with the goal “clean deploy” to have a full test and maven repo deployment on success. The seconday project have the goal “clean package org.codehaus.cargo:cargo-maven2-plugin:redeploy -Dmaven.test.skip=true”. Inside the configuration of the primary job is the section with post build actions. Define here the secondary project to be build only on success of the primary build. Deployments can go wrong and should not have any effect on the primary build. Build trigger for the primary project is source code changes checked every minute (“* * * * *” as time plan). Changes by each developer force a complete junit and integration test of the module and new deployed artifacts inside the maven repo like nexus for the rest of the team. A little bit later is then the new application ready to use. With different profiles is it possible to define DEV,QA and PROD target server inside one maven project pom.

Tomcat needs credentials of a user with explicit rights granted for successful remote deployments. See the following excerpt of the tomcat-user.xml inside the conf folder of your tomcat instance: