Showing posts with label spring. Show all posts
Showing posts with label spring. Show all posts

Sunday, February 7, 2016

Spring reloadable message source

Spring provides you to externalize your messages so that it can be changed without application restart. Add following snippet to your spring configuration.
    <bean id="messageSource"
          class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>${messages.file}</value>
            </list>
        </property>
        <property name="cacheSeconds" value="1" />
    </bean>

The messages.file is pointing to property loaded by Spring PropertyConfigurer. For development purposes you can keep the messages file bundled with your project in classpath but for real deployment it will be outside.
The value should be like classpath:messages where the messages.properties file is kept in src/main/resources. The value can be messages.file=file:D:/config/messages if its kept out at this location.
The Spring messages are by default internalized so if you have done that setup it can pickup files like messages_en_GB.properties as per the locale.

Spring externalize application configuration

To configure your application is different environment using different setup use the following in Spring framework -
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:default.properties</value>
                <value>file:${APPLICATION_CONFIG_HOME}/application.properties</value>
            </list>
        </property>
        <property name="ignoreResourceNotFound" value="true" />
        <property name="searchSystemEnvironment" value="true" />
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    </bean>
By default it will read the default.properties available in your application classpath. Typically it is available at src/main/resources/default.proerties.

Setup environment variable APPLICATION_CONFIG_HOME which points to directory where customer application.properties is available. If the file is available then it will override those properties which you have specified in that file.

For local development user need not required to define this as mostly developers will use the default.properties.

This setup provies an option to override if required in a particular environment e.g. QA, performance, staging, production, etc.

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.

Monday, December 28, 2009

Execute stored procedure in spring with return value and out parameters

Following code example shows how to execute stored procedure in spring with return value and out parameters. The comment along with the code explains the usage.


import java.math.BigDecimal;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;

public class StoredProcedureExampleDAO extends SimpleJdbcCall {

public JdbcDequeueTicketDAO(final JdbcTemplate jdbcTemplate) {
super(jdbcTemplate);
// Here declare all the IN and OUT parameters defined for the stored
// procedure
declareParameters(new SqlParameter("CountryCode", Types.VARCHAR),
new SqlOutParameter("CountryName", Types.VARCHAR));
// Register the stored procedure name
withProcedureName("getCountryName");
// This ensures the stored procedure return value also gets populated
// in the returned Map with key "return".
withReturnValue();
}

public final String getCountryName(final String countryCode) {
// Map to send the IN params values.
Map inParams = new HashMap();
inParams.put("CountryCode", countryCode);

// Map for the OUT params and return value.
Map outParams = null;
try {
outParams = execute(inParams);
} catch (Throwable t) {
throw new DataAccessException("Failed to get the country name", t);
}
if (null != outParams) {
BigDecimal returnValue = (BigDecimal) outParams.get("return");
// The logic of getCountryName stored procedure is that its
// returns 1 if execution is successful otherwise returns 0.
if (null != returnValue && 1 == returnValue.intValue()) {
// On success read the CountryName value
String countryName = (String) outParams.get("CountryName");
return countryName;
}
}
throw new DataAccessException("Failed to get the country name");
}

}

Thursday, November 19, 2009

SpringSource Tool Suite

I have started using STS for the past 3-4 months. The tool is powered by the latest Eclipse version Galileo and comes bundled with useful plugins for Spring based development. The tool also comes with the maven plugin bundled in. I always use Maven and Spring for all my Java projects so I am enjoying this tool.

The suite also comes with Apache Tomcat server called TC Server. The server comes with a web application named "Insight". This web application tracks performance of the web applications deployed in this server. The application have a nice UI to drill down the statistics to pin point the code hampering the performance. No doubt the tool is very helpful to debug the code and find the performance bottlenecks. The beauty is no configurations are required at all.

Thursday, May 21, 2009

Apache cxf using annotations and integration with Spring

Today I will show you how you can create a webservice using Apache CXF version 2.2.1. I will be building this webservice on top of my previous application.

Create a interface AirlineManager to expose methods over webservice. The create method takes airline code and name to create a Airline record in database. Annotation @WebService tells that this is a interface for webservice.

package com.travel;

import javax.jws.WebService;

@WebService
public interface AirlineManager {
public void create(String code, String name);
}

Implement the above webservice interface. We are using AirlineDao created in earlier post. Notice the @WebService(endpointInterface = "com.travel.AirlineManager") which tells that this implementation is for AirlineManager interface.

package com.travel;

import com.travel.dao.AirlineDao;
import javax.jws.WebService;

@WebService(endpointInterface = "com.travel.AirlineManager")
public class AirlineManagerImpl implements AirlineManager {
private AirlineDao airlineDao;

public AirlineManagerImpl(AirlineDao aAirlineDao) {
airlineDao = aAirlineDao;
}

@Override
public void create(String code, String name) {
airlineDao.create(code, name);
}
}

Add this in the spring-context.xml. Here we are importing some cxf beans, defining bean AirlineManagerImpl and creating airlineManagerService webservice.

<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-http-jetty.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

<bean id="airlineManager" class="com.kaleconsultants.travel.AirlineManagerImpl">
<constructor-arg><ref bean="airlineDao"/></constructor-arg>
</bean>

<jaxws:endpoint id="airlineManagerService" implementor="#airlineManager" address="/AirlineManagerService" />

Add this in your web.xml.

<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

Deploy the application in tomcat and your webservice is ready. You can check the wsdl http://host:port/travel/AirlineManagerService?wsdl.

To test the webservice, you need to create a client. You can use wsdl2java available in the bin directory of cxf.

Execute this command, this will generate the wsdl stubs.
wsdl2java http://host:port/travel/AirlineManagerService?wsdl

Write a client like this and there you go.......

package com.travel;

public class ClientTest {
public static void main(String[] args) {
AirlineManagerImplService service = new AirlineManagerImplService();
AirlineManager airlineManager = service.getAirlineManagerImplPort();
airlineManager.create("IC", "Indian");
}
}

Wednesday, May 20, 2009

Hibernate integration with Spring

In my last post Basic Hibernate Annotations example, I wrote about a simple hibernate example. Today I will take that example forward and show you how you can integrate hibernate with Spring. I used Spring version 2.5.6.SEC01.

Create spring-context.xml file. We define a spring datasource, hibernate session factory, hibernate template(spring wrapper api of hibernate session), transaction manager. Bean airlineDao is configured to use annotation based transaction handling. The "<tx:annotation-driven/>" actually enables Spring container to execute methods under transaction, if transaction annotations are used.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

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

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource"><ref bean="dataSource"/></property>
<property name="configLocation"><value>classpath:hibernate.cfg.xml</value></property>
<property name="configurationClass"><value>org.hibernate.cfg.AnnotationConfiguration</value></property>
</bean>

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>

<tx:annotation-driven/>

<bean id="airlineDao" class="com.travel.dao.AirlineDao">
<property name="hibernateTemplate"><ref bean="hibernateTemplate"/></property>
</bean>
</beans>

Create AirlineDao class. Notice the @Transactional (readOnly = true) annotation which brings the execution of this class under transaction. The create method have (readOnly = false) because in this method we are actually updating the table.

package com.travel.dao;

import com.travel.domain.Airline;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Transactional (readOnly = true)
public class AirlineDao extends HibernateDaoSupport {
@Override
@Transactional (readOnly = false)
public void create(String code, String name) {
Airline airline = new Airline();
airline.setCode(code);
airline.setName(name);
getHibernateTemplate().save(airline);
}
}

Add the below xml in your web.xml. This Spring ContextLoaderListener initializes the spring beans defined in file spring-context.xml (we created above).

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/spring-context.xml</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Create a simple servlet to test the DAO. The execution of this servlet will create a new airline record in airline table.

package com.travel.servlet;

import com.kaleconsultants.travel.dao.AirlineDao;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AirlineServlet extends HttpServlet {
private static final long serialVersionUID = 2409603422056073641L;

protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {

String code = request.getParameter("code");
String name = request.getParameter("name");
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
AirlineDao airlineDao = (AirlineDao) context.getBean("airlineDao");
airlineDao.create(code, name);
}
}