Tag Archives: spring

How to configure a secure JMS connection using Spring

In a comment to my previous post about configuring JMS via Spring, Vikas Kadam asked about configuring a connection to a secure TIBCO EMS topic or queue. As fate would have it, the next issue I dealt with was adding this to my own application. What worked for me was using Spring’s UserCredentialsConnectionFactoryAdapter as my connection factory for my JmsTemplate. The final configuration looked like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
 
  <bean id="propertyConfigurer"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location"
      value="file:${catalina.home}/conf/jms.properties" />
  </bean>
 
  <bean id="messageSender"
    class="com.stevideter.spring.jms.MessageSender">
    <property name="jmsTemplate" ref="jmsTemplate" />
  </bean>
 
  <bean id="jmsTemplate"
    class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory"
      ref="userCredentialsConnectionFactory" />
    <property name="defaultDestinationName"
      value="${jms.defaultdestinationname}" />
    <property name="pubSubDomain" value="${jms.istopic}" />
  </bean>
 
  <bean id="userCredentialsConnectionFactory"
    class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
    <property name="targetConnectionFactory">
      <ref bean="topicConnectionFactory" />
    </property>
    <property name="username" value="${jms.username}" />
    <property name="password" value="${jms.password}" />
  </bean>
 
  <bean id="topicConnectionFactory"
    class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiTemplate" ref="jndiTemplate" />
    <property name="jndiName"
      value="${jms.connectionfactory}" />
  </bean>
 
  <bean id="jndiTemplate"
    class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
      <props>
        <prop key="java.naming.factory.initial">
          com.tibco.tibjms.naming.TibjmsInitialContextFactory
        </prop>
        <prop key="java.naming.provider.url">
          ${jms.jndicontexturl}
        </prop>
      </props>
    </property>
  </bean>
</beans>

Simplifying Spring’s JMS configuration for JndiTemplate

I’ve spent several days, off and on, wrestling with a chicken-and-egg configuration issue.

I have an application that uses Spring 2.0 and is deployed to Tomcat 5.5. We make heavy use of Tomcat’s JNDI for configuring things like our database connections.

We’re adding JMS functionality to our application; at this point, we merely need to send events to an existing Tibco EMS 4.4 Topic.

Following the various online tutorials, I was able to use Spring to make my JMS code very lightweight. I was pretty happy with things overall, until I encountered the final problem of setting up the configuration.

The Tibco EMS Server provides its own JNDI services, which I need to connect to the correct topic connection factory. I can use Spring’s JndiTemplate to configure this additional JNDI connection, but I kept hitting one problem. In every environment I’m going to deploy to, the value for java.naming.provider.url will be different. Because JndiTemplate is using

for setting the environment, I can’t use a separate JNDI lookup to populate that value out of Tomcat’s JNDI.

I needed to abstract this value out of my war file, into a configuration file that can stay on each server, so I don’t have to change it every time. This is an application that gets deployed fresh each new revision, and the client wasn’t going to be happy to have to extract the war file and then edit a config file, when that’s never been needed in the past. In addition, each server we’re deploying to already has a JNDI configuration for the Tibco EMS server. But, no matter how I tried, I could not find a way to configure the Tomcat JNDI to let me access those values from the Spring configuration file within the application.

The solution I found that finally worked was to use a PropertyPlaceholderConfigurer that pointed to a file in the tomcat conf directory. The final hurdle I had to jump was the correct configuration. If I used property=”location” value=”${catalina.home}/conf/jms.properties”, Spring would attempt to resolve the value from the servlet container by prepending a slash in front of the catalina.home directory. If I attempted to use a relative path, tomcat wouldn’t allow me open and read the file. I finally hit on prefixing the path with “file:” which was the magic to let Spring know I meant an absolute file path.

I am annoyed I have to add a configuration file, but at least it’s one more place where we can set the value and forget about it for future deployments.

In case anybody hits this combination of problems, here’s what finally worked:

<?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:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/jee 
       http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
 
           <bean id="propertyConfigurer"
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations">
                <list>
                    <value>file:${catalina.home}/conf/jms.properties</value>
                    <value>/WEB-INF/jdbc.properties</value>
                </list>
            </property>
        </bean>
 
    <bean id="messageSender"  
             class="com.stevideter.spring.jms.MessageSender">
        <property name="jmsTemplate" ref="jmsTemplate" />
    </bean>
 
    <bean id="jmsTemplate" 
              class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="topicConnectionFactory" />
        <property name="defaultDestinationName">
            <jee:jndi-lookup jndi-name="java:comp/env/jms/eventdestname"/>
        </property>
        <property name="pubSubDomain" value="true" />
    </bean>
 
    <bean id="topicConnectionFactory" 
             class="org.springframework.jndi.JndiObjectFactoryBean">
       <property name="jndiTemplate" ref="jndiTemplate"/>
       <property name="jndiName" value="FTTopicConnectionFactory"/>
    </bean>
 
    <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
           <property name="environment">
                  <props>
                         <prop key="java.naming.factory.initial">
                            com.tibco.tibjms.naming.TibjmsInitialContextFactory
                         </prop>
                         <prop key="java.naming.provider.url">
                            ${jms.jndicontexturl}
                         </prop>
                  </props>
           </property>
    </bean>
</beans>

Using parent bean definitions in Spring

This post on the JavaRanch Big Moose Saloon led me to fire up Eclipse and write some test code. The question is basically how can you use the ability to map a parent bean as part of a bean definition in Spring.

Let’s look at three classes and see how they can be mapped using Spring.

public abstract class SuperBean {
	private int id;
	private String name;
 
	public int getId() {
		return id;
	}
 
	public void setId(int id) {
		this.id = id;
	}
 
	public String getName() {
		return name;
	}
 
	public void setName(String name) {
		this.name = name;
	}
 
}
 
public class SubBean extends SuperBean {
 
	private String newProperty;
 
	public String getNewProperty() {
		return newProperty;
	}
 
	public void setNewProperty(String newProperty) {
		this.newProperty = newProperty;
	}
 
}
 
public class DifferentBean {
	private int id;
	private String name;
	private String myProperty;
 
	public int getId() {
		return id;
	}
 
	public void setId(int id) {
		this.id = id;
	}
 
	public String getName() {
		return name;
	}
 
	public void setName(String name) {
		this.name = name;
	}
 
	public String getMyProperty() {
		return myProperty;
	}
 
	public void setMyProperty(String myProperty) {
		this.myProperty = myProperty;
	}
 
}

now let’s map them in Spring:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
 
    <bean id="superBean" abstract="true"
        class="com.stevideter.spring.SuperBean">
        <property name="id" value="1" />
        <property name="name" value="superBean" />
    </bean>
 
    <bean id="subBean" class="com.stevideter.spring.SubBean"
        parent="superBean">
        <property name="id" value="2" />
        <property name="newProperty" value="subBean" />
    </bean>
 
    <bean id="differentBean" class="com.stevideter.spring.DifferentBean"
        parent="superBean">
        <property name="id" value="3" />
        <property name="myProperty" value="differentBean" />
    </bean>
</beans>

And now let’s write a simple app to show what happens with these mappings:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class TestClass {
 
    public static void main(String[] args) {
 
        ApplicationContext context = new ClassPathXmlApplicationContext(
                new String[] {"applicationContext.xml"});
 
        SubBean subBean = (SubBean)context.getBean("subBean");
        System.out.printf("ID: %d, Name: %s, Property: %s\n",
                                subBean.getId(), subBean.getName(), subBean.getNewProperty());
 
        DifferentBean differentBean = (DifferentBean)context.getBean("differentBean");
        System.out.printf("ID: %d, Name: %s, Property: %s\n",
                                differentBean.getId(), differentBean.getName(),
                                differentBean.getMyProperty());
    }
}

If we run this class, we get the following results:

ID: 2, Name: superBean, Property: subBean
ID: 3, Name: superBean, Property: differentBean

What we learn from this is that you can use the parent attribute to map to a parent bean definition that your bean class doesn’t inherit from. What’s necessary is that the classes are compatible, which means that the child class has all the properties that are defined in the parent class. In fact, the documentation notes you don’t have to declare a class on the parent definition at all.

I find it more useful to think of the parent definition as a template, to avoid the trap of thinking it is an object-oriented style of inheritance. Another way to think of it is as a parent interface for the child bean; you must implement these properties in order to use this definition.

Processing Stored Procedure result sets in Spring

Recently, I was using Spring‘s JDBCTemplate for my Data Access Layer (DAL). I had a stored procedure that returned a result set, and had to spend quite a bit of search time finding an example of how to process it.

I managed to work it out using both the method of overriding Spring’s StoredProcedure and using the simple JDBCTemplate.query(sql, args, rowMapper). I found the latter to be simpler, since it doesn’t involve a inner class, etc., so here’s a complete example for anyone else who might need to try. Note the assumption that this is a Spring-managed application, so the dataSource is being injected.

This works as early as Spring 1.2.9 and Java 1.3.

package com.stevideter.business.dal.spring;
 
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
 
import javax.sql.DataSource;
 
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
 
import com.stevideter.business.Customer;
import com.stevideter.business.ApplicationException;
 
/**
 * CustomerSpringDao ...
 * @author stevi.deter@gmail.com
 * @version     %I%, %G%
 * @since       1.0
 **/
 
public class CustomerSpringDao {
 
    private JdbcTemplate jdbcTemplate;
 
    public Customer get(Long accountNumber) throws ApplicationException {
        if (accountNumber == null) {
            throw new IllegalArgumentException();
        }
        if (getJdbcTemplate() == null) {
            throw new ApplicationException(ApplicationException.NULL_DAO);
        }
        try {
            List customers = getJdbcTemplate().query(
                    "call PACKAGE.GET_CUSTOMER(?)",
                    new Object[] { accountNumber }, new CustomerMapper());
            if (CollectionUtils.isNotEmpty(customers)) {
                // return the first one
                return (Customer)customers.get(0);
            }
            return null;
        } catch (DataAccessException ex) {
            throw new ApplicationException(ApplicationException.DATA_ACCESS_ERROR);
        }
    }
 
    /**
    * CustomerMapper processes a ResultSet to populate a Customer object
    * @author stevi.deter@gmail.com
    * @version     %I%, %G%
    * @since       1.0
    *
     */
    protected static final class CustomerMapper implements RowMapper {
 
        public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
            Customer customer = new Customer();
            customer.setAccountNumber(new Long(rs.getLong("ACCOUNTNUMBER")));
            customer.setLastName(StringUtils.trimToNull(rs.getString("LASTNAME")));
            customer.setFirstName(StringUtils.trimToNull(rs.getString("FIRSTNAME")));
            return customer;
        }
    }
    /**
     * Spring DI for the datasource. instantiates the JdbcTemplate
     * @param dataSource
     */
    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
    /**
     * @return the jdbcTemplate
     */
    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }
}