Tuesday, June 11, 2013

Simple slf4j configuration with Maven

Just add the following dependencies to your project pom.xml. The slf4j logging will be up and running with default implementation of logback configuration. The default configuration shows logs of DEBUG and above level for all packages.

Each dependencies are explained below -


  1. slf4j-api - slf4j api which you will use in your code to log messages.
  2. commons-logging - note the version this is too exclude all the commons-logging dependencies coming from other dependencies of your project. This version is available at http://version99.qos.ch/commons-logging/commons-logging/99-empty/
  3. logback-* - logback implementation which will be used to configure/control the logging. You can choose to use log4j or other implementation also.
  4. jcl-over-slf4j - enables migration from commons logging to slf4j without any code changes
  5. log4j-over-slf4jenables migration from log4j logging to slf4j without any code changes
  6. jul-over-slf4jenables migration from java util logging to slf4j without any code changes
  7. osgi-over-slf4jenables migration from osgi logging to slf4j without any code changes


        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.5</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>99-empty</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.0.11</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.0.11</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-access</artifactId>
            <version>1.0.11</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <version>1.7.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jul-to-slf4j</artifactId>
            <version>1.7.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>osgi-over-slf4j</artifactId>
            <version>1.7.5</version>
            <scope>runtime</scope>
        </dependency>

Thursday, June 6, 2013

Spring MVC setup using Java Config

Add following config in the web.xml. The following config registers Spring listener. The listener knows that the configuration is based on Java Config by context param "contextClass". The context param "contextConfigLocation" tells the starting configuration class.
 <context-param>
  <param-name>contextClass</param-name>
  <param-value>
   org.springframework.web.context.support.AnnotationConfigWebApplicationContext
  </param-value>
 </context-param>

 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>com.project.config.ApplicationConfiguration</param-value>
 </context-param>

 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
Sample configuration class. Note the "@Configuration" which tells that this class is a configuration class. The below configuration will scan package com.project and look for @Configuration, @Service, @Repository, @Component annotated class and create beans. Note that @Controller is excluded as I like to keep that separate in dispacther servlet context (explained later in the article). Also "WebConfiguration.class" is excluded as it will be used in the dispatcher servlet context.
 @Configuration
 @ComponentScan(basePackages = "com.project", excludeFilters = { @Filter(value = WebConfiguration.class, type = FilterType.ASSIGNABLE_TYPE),
   @Filter(value = Controller.class) })
 public class ApplicationConfiguration {
 }
Add following config in the web.xml. The following config registers a dispatcher servlet. The dispatcher servlet routes urls to the respective controller. In this example urls ending with ".do" will be handled by Spring MVC.

The servlet knows that the configuration is based on Java Config by init param "contextClass". The init param "contextConfigLocation" tells the starting configuration class.
 <servlet>
  <servlet-name>SpringDispatcher</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
   <param-name>contextClass</param-name>
   <param-value>
    org.springframework.web.context.support.AnnotationConfigWebApplicationContext
   </param-value>
  </init-param>
  <init-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>com.project.server.config.WebConfiguration</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>SpringDispatcher</servlet-name>
  <url-pattern>*.do</url-pattern>
 </servlet-mapping>
Sample configuration class. Note the "@Configuration" which tells that this class is a configuration class. The below configuration will scan package "com.project" and look for @Configuration, @Component annotated class and create beans. Note that @Service, @Repository are excluded as I like to keep that separate in application context (see above). Also "ApplicationConfiguration.class" is excluded as it will be used in the application context.
 @Configuration
 @ComponentScan(basePackages = "com.project", excludeFilters = { @Filter(value = Service.class), @Filter(value = Repository.class),
   @Filter(value = ApplicationConfiguration.class, type = FilterType.ASSIGNABLE_TYPE) })
 @EnableWebMvc
 public class WebConfiguration {
 }

Wednesday, June 5, 2013

Spring MVC - HTTP Status 406

If you have encountered following errors with Spring MVC returning JSON response using @ResponseBody -

  1. On the broswer when accessing a resource -> HTTP Status 406 - The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.
  2. In the logs -> org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

Then here is the explanation and solution -

Say for example you have this controller -
@Controller
public class TestController {
    @RequestMapping(value = "/test")
    public @ResponseBody Test test() {
        return new Test();
    }
}
The Test POJO -
public class Test {
    private String name;

    protected String getName() {
        return name;
    }
}
Notice that the POJO has only one getter and that too protected.

You will get the mentioned errors due to the above reason.

The POJO which is getting returned as @ResponseBody must have at least one public getter.