Webservice getting started guide

Draft description of how to setup a maven project for providing REST webservices using Jersey.

Project setup

The following project setup description assumes Eclipse is used, and that Eclipse is maven aware (i.e. can create maven based projects).

Choose to create a new project, and as type select Maven Project. Accept the first set of defaults and move forward to choosing archetype. As archetype select webapp-javaee6. On the next page in the wizzard fill in the appropriate Artifact and Group ID, and accept the project.

Next open the pom.xml file for the newly created project to edit it.

In the dependencies section insert the appropriate bitrepository dependencies and the following required for jersey:

Jersey dependencies
    <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-server</artifactId>
      <version>1.8</version>
    </dependency>

    <dependency>
      <groupId>javax.ws.rs</groupId>
      <artifactId>jsr311-api</artifactId>
      <version>1.1</version>
    </dependency>

Besides the dependencies add the usual maven stuff related to bitrepository modules e.g.:

  • Parent pom
  • Dependencies (those which are not covered above)
  • Repositories (if needed)
  • Scm section
  • Issue Management section
  • ciManagement section
  • Distribution management section
  • Organization

If the above sounds nuts, take a look at the pom.xml for the bitrepository-webclient module, and use that as a basis.

Adding boot strapping files/code

To enable an applicationserver (say Tomcat), to expose the REST methods, a web.xml file needs to be setup. The file should be placed in src/main/webapp/WEB-INF/web.xml. web.xml file from the bitrepository-webclient can serve as an example:

Bitrepository-webservice web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
  <display-name>Bitrepository webservice</display-name>

  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index-v1.html</welcome-file>
  </welcome-file-list>

  <servlet>
    <servlet-name>Bitrepository-webclient</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>org.bitrepository.webservice</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>Bitrepository-webclient</servlet-name>
    <url-pattern>/repo/*</url-pattern>
  </servlet-mapping>

  <listener>
    <listener-class>org.bitrepository.webservice.ShutdownListener</listener-class>
  </listener>
</web-app>

The content of the <param-value> element inside <init-param> should contain the name of the package containing the JAX-RS (JRS-311) annotated classes and methods.

The <listener-class> element is handy to implementing a class to handle startup and shutdown of the webapp. See bitrepository-webclient for reference.

To expose methods as REST calls JAX-RS (JRS-311) annotations should be used. Documentation hereof can be found here.

For integration with the bitrepository-webclient it is desired that a html page is made which should serve as the access method of the service. This way it can be referenced by the webclient and put on it as a tab.

Logback logging

If nothing is done, logback logs will end up in tomcats 'catalina' log. To change this the class LogbackConfigLoader below can be used.

By running its constructor with the path and filename to a logback configuration file (i.e. logback.xml), logback can be configured. This should be done from the 'ShutdownListener' referred to in the web.xml file above.

LogbackConfigLoader
public class LogbackConfigLoader {
	private Logger log = LoggerFactory.getLogger(LogbackConfigLoader.class);

	public LogbackConfigLoader(String configFileLocation) throws IOException, JoranException{
		LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
		File configFile = new File(configFileLocation);
		if(!configFile.exists()){
			throw new IOException("Logback External Config File Parameter does not reference a file that exists");
		}

		if(!configFile.isFile()){
			throw new IOException("Logback External Config File Parameter exists, but does not reference a file");
		}

		if(!configFile.canRead()){
			throw new IOException("Logback External Config File exists and is a file, but cannot be read.");
		}

		JoranConfigurator configurator = new JoranConfigurator();
		configurator.setContext(loggerContext);
		loggerContext.reset();
		configurator.doConfigure(configFileLocation);
		log.info("Configured Logback with config file from: " + configFileLocation);

	}
}