/*
* Copyright (c) 2014-2016 Red Hat, Inc. and/or its affiliates.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Cheng Fang - Initial API and implementation
*/
package org.jberet.support.io;
import java.io.Serializable;
import javax.batch.api.BatchProperty;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Session;
import javax.naming.InitialContext;
import org.jberet.support._private.SupportLogger;
import org.jberet.support._private.SupportMessages;
/**
* The base class for {@link JmsItemReader} and {@link JmsItemWriter}.
*
* @see JmsItemReader
* @see JmsItemWriter
* @since 1.1.0
*/
public abstract class JmsItemReaderWriterBase extends ItemReaderWriterBase {
/**
* This field holds an optional injection of {@code javax.jms.Destination}. When {@link #destinationLookupName}
* property is specified in job xml, this field is ignored and {@link #destinationLookupName} is used to look up
* JMS destination. The application may implement a {@code javax.enterprise.inject.Produces} method to satisfy
* this dependency injection.
*/
@Inject
protected Instance<Destination> destinationInstance;
/**
* This field holds an optional injection of {@code javax.jms.ConnectionFactory}. When {@link #connectionFactoryLookupName}
* property is specified in job xml, this field is ignored and {@link #connectionFactoryLookupName} is used to
* look up JMS {@code ConnectionFactory}. The application may implement a {@code javax.enterprise.inject.Produces}
* method to satisfy this dependency injection.
*/
@Inject
protected Instance<ConnectionFactory> connectionFactoryInstance;
/**
* JNDI lookup name for the JMS {@code Destination}. Optional property and defaults to null. When specified in
* job xml, it has higher precedence over {@link #destinationInstance} injection
*/
@Inject
@BatchProperty
protected String destinationLookupName;
/**
* JNDI lookup name for the JMS {@code ConnectionFactory}. Optional property and defaults to null. When specified in
* job xml, it has higher precedence over {@link #connectionFactoryInstance} injection.
*/
@Inject
@BatchProperty
protected String connectionFactoryLookupName;
/**
* The string name of the sessionMode used to create JMS session from a JMS connection. Optional property, and
* defaults to null. When not specified, JMS API {@link javax.jms.Connection#createSession()} is invoked to create
* the JMS session. When this property is specified, its value must be one of the following:
* <ul>
* <li>{@code AUTO_ACKNOWLEDGE}
* <li>{@code DUPS_OK_ACKNOWLEDGE}
* <li>{@code CLIENT_ACKNOWLEDGE}
* <li>{@code SESSION_TRANSACTED}
* </ul>
* Example properties in job xml:
* <pre>
* <property name="sessionMode" value="DUPS_OK_ACKNOWLEDGE"/>
* </pre>
* or,
* <pre>
* <property name="sessionMode" value="SESSION_TRANSACTED"/>
* </pre>
* See JMS API {@link javax.jms.Connection#createSession(int)} for more details.
*/
@Inject
@BatchProperty
protected String sessionMode;
protected Destination destination;
protected ConnectionFactory connectionFactory;
protected Connection connection;
protected Session session;
public void open(final Serializable checkpoint) throws Exception {
InitialContext ic = null;
try {
if (destinationLookupName != null) {
ic = new InitialContext();
destination = (Destination) ic.lookup(destinationLookupName);
} else {
destination = destinationInstance.get();
}
if (connectionFactoryLookupName != null) {
if (ic == null) {
ic = new InitialContext();
}
connectionFactory = (ConnectionFactory) ic.lookup(connectionFactoryLookupName);
} else {
connectionFactory = connectionFactoryInstance.get();
}
connection = connectionFactory.createConnection();
final int jmsMajorVersion = connection.getMetaData().getJMSMajorVersion();
if (sessionMode != null) {
final int sessionModeInt;
if (sessionMode.equals("AUTO_ACKNOWLEDGE")) {
sessionModeInt = Session.AUTO_ACKNOWLEDGE;
} else if (sessionMode.equals("DUPS_OK_ACKNOWLEDGE")) {
sessionModeInt = Session.DUPS_OK_ACKNOWLEDGE;
} else if (sessionMode.equals("CLIENT_ACKNOWLEDGE")) {
sessionModeInt = Session.CLIENT_ACKNOWLEDGE;
} else if (sessionMode.equals("SESSION_TRANSACTED")) {
sessionModeInt = Session.SESSION_TRANSACTED;
} else {
throw SupportMessages.MESSAGES.invalidReaderWriterProperty(null, sessionMode, "sessionMode");
}
if (jmsMajorVersion > 1) {
session = connection.createSession(sessionModeInt);
} else {
session = sessionModeInt == Session.SESSION_TRANSACTED ?
connection.createSession(true, Session.AUTO_ACKNOWLEDGE) :
connection.createSession(false, sessionModeInt);
}
} else {
session = jmsMajorVersion > 1 ? connection.createSession() :
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
}
} finally {
if (ic != null) {
ic.close();
}
}
}
protected void close() {
if (session != null) {
try {
session.close();
} catch (final JMSException e) {
SupportLogger.LOGGER.tracef(e, "Failed to close JMS session %s%n", session);
}
session = null;
}
if (connection != null) {
try {
connection.close();
} catch (final JMSException e) {
SupportLogger.LOGGER.tracef(e, "Failed to close JMS connection %s%n", connection);
}
connection = null;
}
}
}