Install this theme

Posts tagged: spring

Spring AOP: Intercepting method with custom annotation

Almost every Spring developer already seen and used @Transactional annotation, responsible for the database transaction demarcation.
It creates an AOP around advice, that starts the database tranaction before method execution and commits (or rollbacks) it, after the execution ends.

This post demonstrates, how to create a custom annotation working like @Transactional and responsible for profling method execution. It uses method intercepting capabilities provided by the Spring AOP, however without utilizing AspectJ.

1. We’ll start with the custom annotation @ProfileExecution, that will mark bean methods we want to profile:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
@Documented
public @interface ProfileExecution {

}

Keep reading

Database-driven message source in Spring

Typical Spring’s message source (see the MessageSource Javadoc) relies on the resource bundles. However it is quite easy to create a custom MessageSource implementation that determines messages from some other external data source.

This post demonstrates how to initialize a database-driven MessageSource and presents two approaches how messages can be saved in the database.

Keep reading

Configuring Spring based Web Application from database or other external data source

The most common usecase to configure Spring’s application context using external properties is a combination of a property file and a PropertyPlaceholderConfigurer bean. If you deploy your application in multiple environments (e.g. development, pre-production, production..) it is a good idea to externalize this configuration file and to bring the application to load this file from external location on startup.

This post demonstrates how to replace the property file by other external data source (especially database) and make it possible to configure a Spring based web application on startup from it.

Keep reading

Oracle Advanced Queuing with Spring and custom Oracle Types

There are already several blog articles on the web about this topic. In this post I want to demonstrate how you can process JMS messages that have been created based on the Oracle Custom Types.

This is also the solution to the common problem: JMS-137: Payload factory must be specified for destinations with ADT payloads.

In the run-up to the post please find below some links how to connect Spring via JMS to the Oracle Advanced Queing:

Assuming following custom oracle data type, queue table and the queue itself were defined in the database:

create or replace type aq_event_obj as object
(
  datetime date,
  id       varchar2(100),
  payload  varchar2(255)
);
sys.dbms_aqadm.create_queue_table(queue_table        => 'T_AQ_EVENT',
                                  queue_payload_type => 'AQ_EVENT_OBJ',
                                  sort_list          => 'PRIORITY, ENQUEUE_TIME',
                                  compatible         => '10.0.0',
                                  primary_instance   => 0,
                                  secondary_instance => 0);
sys.dbms_aqadm.create_queue(queue_name     => 'Q_AQ_EVENT',
                            queue_table    => 'T_AQ_EVENT',
                            queue_type     => sys.dbms_aqadm.normal_queue,
                            max_retries    => 5,
                            retry_delay    => 0,
                            retention_time => 0);

First step is a standard procedure creating JMS Connection Factory, Event Queue and JMS Template in Spring described in the posts above (see links). Just a brief overview for this here:

<bean id="jmsQueueConnectionFactory" class="oracle.jms.AQjmsFactory"
	factory-method="getQueueConnectionFactory">
	<constructor-arg index="0" ref="dataSource" />
</bean>
<bean id="aqEventQueue" class="net.javaforge.blog.oracle.aq.OracleAqQueueFactoryBean">
	<property name="connectionFactory" ref="jmsQueueConnectionFactory" />
	<property name="oracleQueueName" value="Q_AQ_EVENT" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
	<property name="connectionFactory" ref="jmsQueueConnectionFactory" />
	<property name="defaultDestination" ref="aqEventQueue" />
</bean>

And the corresponding java classes:

public abstract class AbstractOracleAqFactoryBean {

	private ConnectionFactory connectionFactory;
	private String oracleQueueName = null;
	private String oracleQueueUser = null;

	@Required
	public void setConnectionFactory(final ConnectionFactory connectionFactory) {
		this.connectionFactory = connectionFactory;
	}

	public String getOracleQueueName() {
		return oracleQueueName;
	}

	@Required
	public void setOracleQueueName(final String oracleQueueName) {
		this.oracleQueueName = oracleQueueName;
	}

	public String getOracleQueueUser() {
		return oracleQueueUser;
	}

	public void setOracleQueueUser(final String oracleQueueUser) {
		this.oracleQueueUser = oracleQueueUser;
	}

	public boolean isSingleton() {
		return false;
	}

	protected AQjmsSession getSession() throws JMSException {
		final AQjmsSession session = (AQjmsSession) connectionFactory
				.createConnection().createSession(true,
						Session.SESSION_TRANSACTED);
		return session;
	}

}

public class OracleAqQueueFactoryBean extends AbstractOracleAqFactoryBean
		implements FactoryBean {

	public Class getObjectType() {
		return javax.jms.Queue.class;
	}

	public Queue getObject() throws JMSException {
		final AQjmsSession session = getSession();
		return session.getQueue(getOracleQueueUser(), getOracleQueueName());
	}

}

Furthermore as soon as we want to process custom oracle data type as message payload, we have to implement the ORADataFactory interface and describe our aq_event_obj type in it.

This interface can be implemented by hand or you can just generate an appropriate implementation with Oracle’s JDeveloper IDE. To save time i have chosen the second option and generated following ugly but fully functional class:

image
public class AQCustomPayloadObject implements ORAData, ORADataFactory {
	
	public static final String _SQL_NAME = "AQ_EVENT_OBJ";
	public static final int _SQL_TYPECODE = OracleTypes.STRUCT;

	protected MutableStruct _struct;

	protected static int[] _sqlType = { 91, 12, 12 };
	protected static ORADataFactory[] _factory = new ORADataFactory[3];
	protected static final AQCustomPayloadObject _AqEventObjFactory = new AQCustomPayloadObject();

	public static ORADataFactory getORADataFactory() {
		return _AqEventObjFactory;
	}

	/* constructors */
	protected void _init_struct(boolean init) {
		if (init)
			_struct = new MutableStruct(new Object[3], _sqlType, _factory);
	}

	public AQCustomPayloadObject() {
		_init_struct(true);
	}

	public AQCustomPayloadObject(java.sql.Timestamp datetime, String id, String payload)
			throws SQLException {
		_init_struct(true);
		setDatetime(datetime);
		setId(id);
		setPayload(payload);
	}

	/* ORAData interface */
	public Datum toDatum(Connection c) throws SQLException {
		return _struct.toDatum(c, _SQL_NAME);
	}

	/* ORADataFactory interface */
	public ORAData create(Datum d, int sqlType) throws SQLException {
		return create(null, d, sqlType);
	}

	protected ORAData create(AQCustomPayloadObject o, Datum d, int sqlType)
			throws SQLException {
		if (d == null)
			return null;
		if (o == null)
			o = new AQCustomPayloadObject();
		o._struct = new MutableStruct((STRUCT) d, _sqlType, _factory);
		return o;
	}

	/* accessor methods */
	public java.sql.Timestamp getDatetime() throws SQLException {
		return (java.sql.Timestamp) _struct.getAttribute(0);
	}

	public void setDatetime(java.sql.Timestamp datetime) throws SQLException {
		_struct.setAttribute(0, datetime);
	}

	public String getId() throws SQLException {
		return (String) _struct.getAttribute(1);
	}

	public void setId(String id) throws SQLException {
		_struct.setAttribute(1, id);
	}

	public String getPayload() throws SQLException {
		return (String) _struct.getAttribute(2);
	}

	public void setPayload(String payload) throws SQLException {
		_struct.setAttribute(2, payload);
	}

}

Now it is time for the magic. We have to override Spring’s default DefaultMessageListenerContainer class by creating our special message consumer that can deal with the aq_event_obj type :

public class AQCustomPayloadMessageListenerContainer extends
		DefaultMessageListenerContainer {

	@Override
	protected MessageConsumer createConsumer(Session session,
			Destination destination) throws JMSException {

		return ((AQjmsSession) session).createConsumer(destination,
				getMessageSelector(),
				AQCustomPayloadObject.getORADataFactory(), null,
				isPubSubNoLocal());

	}
}

And the corresponding Spring’s XML configuration:

<bean id="jmsContainer"
	class="net.javaforge.blog.oracle.aq.AQCustomPayloadMessageListenerContainer">
	<property name="connectionFactory" ref="jmsQueueConnectionFactory" />
	<property name="destination" ref="aqEventQueue" />
	<property name="messageListener" ref="aq.receiver" />
	<property name="sessionTransacted" value="true" />
	<property name="transactionManager" ref="tx.manager" />
</bean>

The only task now is to implement the message receiver:

@Named("aq.receiver")
public class AQReceiver implements MessageListener {

	private static final Logger logger = LoggerFactory
			.getLogger(AQReceiver.class);

	@Override
	public void onMessage(Message message) {
		try {
			AQjmsAdtMessage msg = (AQjmsAdtMessage) message;
			AQCustomPayloadObject obj = (AQCustomPayloadObject) msg.getAdtPayload();

			logger.info("Id: {}", obj.getid());
			logger.info("Datetime: {}", obj.getDatetime());
			logger.info("Payload: {}", obj.getPayload());

		} catch (Exception e) {
			logger.error("Error receiving queue message!", e);
		}
	}
}