How to Enable TLS1.1 in Java7 for Axis1 webservice client - salesforce

Summary: Salesforce.com recently disabled TLSv1 for their sandbox instances(test.salesforce.com) and can only support TLSv1.1 and above for API integrations for both inbound and outbound requests.
I am using Java Axis1.0 client code with JDK 7.0 to connect (via webservice soap) to salesforce.com. I get exception "UNSUPPORTED_CLIENT: TLS 1.0 has been disabled in this organization. Please use TLS 1.1 or higher when connecting to Salesforce using https."
With Java7.0
Supported Protocols:SSLv2Hello, SSLv3, TLSv1, TLSv1.1, TLSv1.2
Enabled Protocols: TLSv1
`With Java8.0
when i try to connect to salesforce.com with java8 client, connection is successful.
Supported Protocols: SSLv2Hello, SSLv3, TLSv1, TLSv1.1, TLSv1.2
Enabled Protocols: TLSv1, TLSv1.1, TLSv1.2`
I have to used Java 7 because our application is using it.
I tried setting vm args:
-Dhttps.protocols=TLSv1.1,TLSv1.2 -Ddeployment.security.SSLv2Hello=false -Ddeployment.security.SSLv3=false -Ddeployment.security.TLSv1=false -Ddeployment.security.TLSv1.1=true -Ddeployment.security.TLSv1.2=true"
but no success.
can you help me to find out settings in Java7 to enable TLSv1.1?

Found a solution:
I had to write custom JSSESocketFactory (because i am using Java webservice Axis1.0 client) and AxisProperties settings.
Something like,
public class TLSSocketSecureFactory extends JSSESocketFactory {
private final String TLS_VERSION_1_1 = "TLSv1.1";
private final String TLS_VERSION_1_2 = "TLSv1.2";
public TLSSocketSecureFactory(#SuppressWarnings("rawtypes") Hashtable attributes) {
super(attributes);
}
#Override
protected void initFactory() throws IOException {
SSLContext context;
try {
context = SSLContext.getInstance(TLS_VERSION_1_1);
context.init(null, null, null);
sslFactory = context.getSocketFactory();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
//printstacktrace or throw IOException
}
}
#Override
public Socket create(String host, int port, StringBuffer otherHeaders, BooleanHolder useFullURL) throws Exception {
if (sslFactory == null) {
initFactory();
}
Socket s = super.create(host, port, otherHeaders, useFullURL);
((SSLSocket) s).setEnabledProtocols(new String[] {TLS_VERSION_1_1, TLS_VERSION_1_2 });
return s;
}
}
AxisProperties.setProperty("axis.socketSecureFactory",TLSSocketSecureFactory.class.getCanonicalName());
This is required only for JDK7. when application is migrated to JDK8, this class is not required. In Java8 TLSv1.1 and TLS1.2 is enabled by default.
Note: Setting VM config at server will not help here for Axis java client.

From Salesforce documentation:
Java 7: Enable TLS 1.1 and TLS 1.2 using the https.protocols Java system property for HttpsURLConnection. To enable TLS 1.1 and TLS 1.2 on non-HttpsURLConnection connections, set the enabled protocols on the created SSLSocket and SSLEngine instances within the application source code.

The solution above works well when the Axis transport is the default HTTPSender. Also, it's useful to know that the new socket factory can be replaced not just with AxisProperties but also with a system property, which can be passed on the command line like this:
-Dorg.apache.axis.components.net.SecureSocketFactory=your.package.TLSv12JSSESocketFactory
Here is the code for my TLSv12JSSESocketFactory:
package your.package;
import java.util.Hashtable;
import java.io.IOException;
import java.net.Socket;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import org.apache.axis.components.net.JSSESocketFactory;
import org.apache.axis.components.net.BooleanHolder;
public class TLSv12JSSESocketFactory extends JSSESocketFactory {
private final String TLS_VERSION_1_2 = "TLSv1.2";
public TLSv12JSSESocketFactory( #SuppressWarnings("rawtypes") Hashtable attributes ) {
super(attributes);
}
#Override
protected void initFactory() throws IOException {
SSLContext context;
try {
context = SSLContext.getInstance( TLS_VERSION_1_2 );
context.init( null, null, null );
sslFactory = context.getSocketFactory();
} catch ( Exception e ) {
throw new IOException( "Could not init SSL factory with TLS context: " + TLS_VERSION_1_2, e );
}
}
#Override
public Socket create( String host, int port, StringBuffer otherHeaders, BooleanHolder useFullURL ) throws Exception {
Socket s = super.create( host, port, otherHeaders, useFullURL );
((SSLSocket) s).setEnabledProtocols( new String[] { TLS_VERSION_1_2 } );
return s;
}
}
In my case I had to change Axis 1.4 using Apache Commons HttpClient as the transport. This involved creating a class implementing interface SecureProtocolSocketFactory. Here is my code:
package your.package;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import javax.net.ssl.SSLSocket;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
public class TLSv12HttpsSocketFactory implements SecureProtocolSocketFactory
{
private static final String TLS_VERSION_1_2 = "TLSv1.2";
private final SecureProtocolSocketFactory base;
public TLSv12HttpsSocketFactory( ProtocolSocketFactory base )
{
if ( base == null || !(base instanceof SecureProtocolSocketFactory) ) throw new IllegalArgumentException();
this.base = (SecureProtocolSocketFactory) base;
}
private Socket acceptOnlyTLS12( Socket socket )
{
if ( socket != null && (socket instanceof SSLSocket) ) {
((SSLSocket) socket).setEnabledProtocols( new String[] { TLS_VERSION_1_2 } );
}
return socket;
}
#Override
public Socket createSocket( String host, int port ) throws IOException
{
return acceptOnlyTLS12( base.createSocket(host, port) );
}
#Override
public Socket createSocket( String host, int port, InetAddress localAddress, int localPort ) throws IOException
{
return acceptOnlyTLS12( base.createSocket(host, port, localAddress, localPort) );
}
#Override
public Socket createSocket( String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params ) throws IOException
{
return acceptOnlyTLS12( base.createSocket(host, port, localAddress, localPort, params) );
}
#Override
public Socket createSocket( Socket socket, String host, int port, boolean autoClose ) throws IOException
{
return acceptOnlyTLS12( base.createSocket(socket, host, port, autoClose) );
}
}
But I also had to modify the org.apache.axis.transport.http.CommonsHTTPSender class (generates a few class files when compiled) like this:
// import the new socket factory
import your.package.TLSv12HttpsSocketFactory;
...
// add this at the end of the initialize() method
// setup to our custom TLSv1.2 socket factory
String scheme = "https";
Protocol baseHttps = Protocol.getProtocol( scheme );
int defaultPort = baseHttps.getDefaultPort();
ProtocolSocketFactory baseFactory = baseHttps.getSocketFactory();
ProtocolSocketFactory customFactory = new TLSv12HttpsSocketFactory( baseFactory );
Protocol customHttps = new Protocol( scheme, customFactory, defaultPort );
Protocol.registerProtocol( scheme, customHttps );

Related

SpringBoot AngularJS webSocket integration

I'm trying to create webSocket on springBoot application.
this is config class:
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/sub");
config.setApplicationDestinationPrefixes("/send");
}
#Override
public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
}
#Override
public void configureClientInboundChannel(ChannelRegistration registration) {
}
#Override
public void configureClientOutboundChannel(ChannelRegistration registration) {
}
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
}
#Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
}
#Override
public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
return true;
}
}
Now from AngularJS I'm trying to connect to websocket using SockJS and Stomp
var socket = new SockJS('/api/ws');
var stompClient = Stomp.over(socket);
stompClient.connect({}, function (frames) {
stompClient.subscribe('/subs/hello', function (data) {
console.log(data);
});
});
When I open console I get this message:
admin-components.js:112173 WebSocket connection to 'wss://proxy.beta.corp.payment21.com/api/ws/135/hwq2yv3q/websocket' failed: Error during WebSocket handshake: Unexpected response code: 502
After 30 seconds I get this:
VM333 sockjs.min.js:2 Uncaught Error: Incompatibile SockJS! Main site uses: "1.4.0", the iframe: "1.0.0".
at s (VM333 sockjs.min.js:2)
And after 30 more seconds:
And it is working...
When I go to network to see details in the frames it says
(Opcode -1)
What is the problem here? Is it the spring configuration or SockJS?
Based on the Spring documentation the supported client SockJS version is 1.0.x
On the browser side, applications can use the sockjs-client (version 1.0.x). It emulates the W3C WebSocket API and communicates with the server to select the best transport option, depending on the browser in which it runs.

Apache Camel - Create mock endpoint to listen to messages sent from within a processor

I have a route as follows:
from(fromEndpoint).routeId("ticketRoute")
.log("Received Tickets : ${body}")
.doTry()
.process(exchange -> {
List<TradeTicketDto> ticketDtos = (List<TradeTicketDto>) exchange.getIn().getBody();
ticketDtos.stream()
.forEach(t -> solaceMessagePublisher.sendAsText("BOOKINGSERVICE.TICKET.UPDATED", t));
ticketToTradeConverter.convert(ticketDtos)
.forEach(t -> solaceMessagePublisher.sendAsText("BOOKINGSERVICE.TRADE.UPDATED", t));
}).doCatch(java.lang.RuntimeException.class)
.log(exceptionMessage().toString() + " --> ${body}");
solaceMessagePublisher is a utility class in application which performs some action on passed object (second argument) and finally converts it to json string and sends to a jms topic (first argument).
SolaceMessagePublisher.java
public void sendAsText(final String destinationKey, Object payload) {
LOGGER.debug("Sending object as text to %s",destinationKey);
String destinationValue = null;
if (StringUtils.isNotEmpty(destinationKey)) {
destinationValue = properties.getProperty(destinationKey);
}
LOGGER.debug("Identified Destination Value = %s from key %s", destinationValue,destinationKey);
if (StringUtils.isEmpty(destinationValue)) {
throw new BaseServiceException("Invalid destination for message");
}
sendAsTextToDestination(destinationValue, payload);
}
public void sendAsTextToDestination(final String destinationValue, Object payload) {
if (payload == null) {
LOGGER.debug(" %s %s",EMPTY_PAYLOAD_ERROR_MESSAGE, destinationValue);
return;
}
final String message = messageCreator.createMessageEnvelopAsJSON(payload, ContextProvider.getUserInContext());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Created message = " + message);
}
jmsTemplate.send(destinationValue, new MessageCreator() {
#Override
public Message createMessage(Session session) throws JMSException {
LOGGER.debug("Creating JMS Text Message");
return session.createTextMessage(message);
}
});
}
I am having a problem in creating a mock endpoint to listen to messages sent to this topic. Question is how to listen to the messages sent to a topic which is out of camel context?
I have tried in my Test using mock:jms:endpoint. It doesn't work.
My Test is as below
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { SiteMain.class })
public class TicketRouteCamelTest extends CamelSpringTestSupport{
#Autowired
protected BaseMessageEnvelopCreator messageCreator;
private static final String MOCK_TICKET_UPDATED_QUEUE = "direct:mockTicketUpdated";
#Before
public void configureMockEndpoints() throws Exception {
//mock input
final AdviceWithRouteBuilder mockRouteAdvice = new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
replaceFromWith(MOCK_TICKET_UPDATED_QUEUE);
}
};
context().getRouteDefinition("ticketRoute").adviceWith(context(), mockRouteAdvice);
}
#Test
public void testTicketRouteWithListOfTickets() throws Exception {
//create test data
TradeTicketDto tradeTicketDto = TradeTestDataHelper.getTradeTicketDto();
//create an exchange and set its body with test data
List<TradeTicketDto> list = new ArrayList<>();
list.add(tradeTicketDto);
list.add(tradeTicketDto);
Exchange requestExchange = ExchangeBuilder.anExchange(context()).build();
requestExchange.getIn().setBody(list);
//create assert on the mock endpoints
MockEndpoint mockTicketUpdatedEndpoint = getMockEndpoint("mock:DEV/bookingservice/ticket/updated");
mockTicketUpdatedEndpoint.expectedBodiesReceived(
messageCreator.createMessageEnvelopAsJSON(list.get(0), ContextProvider.getUserInContext()),
messageCreator.createMessageEnvelopAsJSON(list.get(1), ContextProvider.getUserInContext()) );
MockEndpoint mockTradeUpdatedEndpoint = getMockEndpoint("mock:DEV/bookingservice/trade/updated");
mockTradeUpdatedEndpoint.expectedBodiesReceived(
messageCreator.createMessageEnvelopAsJSON(list.get(0).getTicketInstruments().get(0), ContextProvider.getUserInContext()),
messageCreator.createMessageEnvelopAsJSON(list.get(0).getTicketInstruments().get(1), ContextProvider.getUserInContext()),
messageCreator.createMessageEnvelopAsJSON(list.get(1).getTicketInstruments().get(0), ContextProvider.getUserInContext()),
messageCreator.createMessageEnvelopAsJSON(list.get(1).getTicketInstruments().get(1), ContextProvider.getUserInContext()));
//send test exchange to request mock endpoint
template.send(MOCK_TICKET_UPDATED_QUEUE, requestExchange);
//test the asserts
assertMockEndpointsSatisfied();
}
}
On running test actual bodies received on mockendpont is 0
Mock is NOT a queue for consumers/producers to exchange data. Its a sink for testing purpose where you can setup expectations on the mock.
If you want to simulate a JMS via some kind of other means, then take a look at the stub component: http://camel.apache.org/stub
Its also listed in the bottom of the testing docs at: http://camel.apache.org/testing

log4j2 queue/topic configuration by spring

Are there any way to configure log4j2 to read Appender attributes from for example a spring bean? I am curious especially in JmsAppender to dynamically set it's target destination based on a parameter read from database and not from JNDI context.
BR
Zoltán
Your best chance is to extend the JMSAppender and override the append methods in the logger. A good example is here
This case , the class extends and uses AMQ to post these messages into. You should be able to extend this from the DB and use API's to get a handle to the Queue or Topic and start appending messages into it. This assumes that you have the right client libraries and permissions to connect to the messaging provider (e.g. in WMQ you may need the QM Name , Queue , Host, port) from the DB (in your case). The extended JMS appender can then be used in your LOG4J2 configuration for sending log messages.
It seems that i found a hybrid soution which is very useful, custom JmsAppender combined with spring context:
#Plugin(name = "OwnJmsAppender", category = "Core", elementType = "appender", printObject = true)
public class OwnJmsAppender extends AbstractAppender {
private final Lock lock = new ReentrantLock();
private Session session;
private Connection connection;
private Destination destination;
private MessageProducer producer;
protected OwnJmsAppender(String name, Filter filter, Layout<? extends Serializable> layout, final boolean ignoreExceptions) {
super(name, filter, layout, ignoreExceptions);
init();
}
#Override
public void append(LogEvent le) {
this.lock.lock();
try {
if (connection == null) {
init();
}
byte[] bytes = getLayout().toByteArray(le);
TextMessage message = session.createTextMessage(new String(bytes, Charset.forName("UTF-8")));
producer.send(message);
} catch (JMSException e) {
LOGGER.error(e);
} finally {
this.lock.unlock();
}
}
#Override
public void stop() {
super.stop();
try {
session.close();
connection.close();
} catch (JMSException e) {
LOGGER.error(e);
}
}
/**
* Reading attributes from log4j2.xml configuration by {#link PluginElement}
* annotation. Also initiates the logger.
*
* #param name
* #param layout
* #param filter
* #return
*/
#PluginFactory
public static OwnJmsAppender createAppender(#PluginAttribute("name") String name,
#PluginElement("PatternLayout") Layout<? extends Serializable> layout, #PluginElement("Filter") final Filter filter) {
if (name == null) {
LOGGER.error("No name provided for OwnJmsAppender");
return null;
}
return new OwnJmsAppender(name, filter, getLayout(layout), true);
}
private static Layout<? extends Serializable> getLayout(Layout<? extends Serializable> layout) {
Layout<? extends Serializable> finalLayout = layout;
if (finalLayout == null) {
finalLayout = PatternLayout.createDefaultLayout();
}
return finalLayout;
}
private void init() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CommonDbConfig.class);
ParameterStorage parameterStorage = (DatabaseParameterStorage) context.getBean("databaseParameterStorage");
// the parameterStorage springbean reads params from database
String brokerUri = parameterStorage.getStringValue("broker.url");
String queueName = "logQueue";
context.close();
try {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerUri);
connection = connectionFactory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue(queueName);
producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
} catch (JMSException e) {
LOGGER.error(e);
}
}
}
And call it from log4j2.xml:
<Configuration>
<Appenders>
<OwnJmsAppender name="jmsQueue">
<PatternLayout pattern="%maxLen{%d{DEFAULT} [%p] - %m %xEx%n}{500}" />
</OwnJmsAppender>
</Appenders>
<Loggers>
<Logger name="com.your.package" level="info" additivity="false">
<AppenderRef ref="jmsQueue" />
</Logger>
</Loggers>
</Configuration>

How does CXF Bus and STSClient deal with SSL Certificate and Proxy?

I'm using CXF 3.1.5, How can I apply proxy settings and trust or ignore SSL certificate when sending out request?
I use CXF in the following two ways.
Using org.apache.cxf.bus to get WSDL definition from IdP or SP, bus.getExtension(WSDLManager.class).getDefinition().
Using org.apache.cxf.ws.security.trust.STSClient to request Security Token.stsClient.requestSecurityToken()
and I think I need to use code for configuration instead of configuration file as my callers send me those information about proxy and SSL certificates.
thanks a lot!
After further research, I found something.
to resolve the first problem, add the following code:
ResourceManager extension = bus.getExtension(ResourceManager.class);
extension.addResourceResolver(new ResourceResolver() {
#Override
public <T> T resolve(String resourceName, Class<T> resourceType) {
return null;
}
#Override
public InputStream getAsStream(String name) {
if (!name.startsWith("https")) {
return null;
}
org.apache.http.client.HttpClient httpClient = HttpUtils.createHttpClient(setting);
HttpGet httpGet = new HttpGet(name);
try {
HttpResponse httpResponse = httpClient.execute(httpGet);
return httpResponse.getEntity().getContent();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
});
then I can get the WSDL definition, but I still don't know how to fix the second problem, I'm trying to use HTTPConduit((HTTPConduit)stsClient.getClient().getConduit()), but when call stsClient.getClient(), cxf will try to load those XML Schema which will lead to the following exception:
org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
at org.apache.cxf.wsdl11.WSDLServiceFactory.create(WSDLServiceFactory.java:170)
at org.apache.cxf.ws.security.trust.AbstractSTSClient.createClient(AbstractSTSClient.java:657)
at org.apache.cxf.ws.security.trust.AbstractSTSClient.getClient(AbstractSTSClient.java:480)
...
Caused by: org.apache.ws.commons.schema.XmlSchemaException: Unable to locate imported document at 'https://...&xsd=ws-trust-1.3.xsd', relative to 'https://...#types1'.
at org.apache.cxf.catalog.CatalogXmlSchemaURIResolver.resolveEntity(CatalogXmlSchemaURIResolver.java:76)
at org.apache.ws.commons.schema.SchemaBuilder.resolveXmlSchema(SchemaBuilder.java:684)
at org.apache.ws.commons.schema.SchemaBuilder.handleImport(SchemaBuilder.java:538)
at org.apache.ws.commons.schema.SchemaBuilder.handleSchemaElementChild(SchemaBuilder.java:1516)
at org.apache.ws.commons.schema.SchemaBuilder.handleXmlSchemaElement(SchemaBuilder.java:659)
at org.apache.ws.commons.schema.XmlSchemaCollection.read(XmlSchemaCollection.java:551)
at org.apache.cxf.common.xmlschema.SchemaCollection.read(SchemaCollection.java:129)
at org.apache.cxf.wsdl11.SchemaUtil.extractSchema(SchemaUtil.java:140)
at org.apache.cxf.wsdl11.SchemaUtil.getSchemas(SchemaUtil.java:73)
at org.apache.cxf.wsdl11.SchemaUtil.getSchemas(SchemaUtil.java:65)
at org.apache.cxf.wsdl11.SchemaUtil.getSchemas(SchemaUtil.java:60)
at org.apache.cxf.wsdl11.WSDLServiceBuilder.getSchemas(WSDLServiceBuilder.java:378)
at org.apache.cxf.wsdl11.WSDLServiceBuilder.buildServices(WSDLServiceBuilder.java:345)
at org.apache.cxf.wsdl11.WSDLServiceBuilder.buildServices(WSDLServiceBuilder.java:209)
at org.apache.cxf.wsdl11.WSDLServiceFactory.create(WSDLServiceFactory.java:162)
... 32 more
Found a solution:
implements HTTPConduitFactory and put it into bus.
bus.setExtension(new MyHTTPConduitFactory(setting), HTTPConduitFactory.class)
In the Factory class:
#Override
public HTTPConduit createConduit(HTTPTransportFactory f, Bus b, EndpointInfo localInfo,
EndpointReferenceType target) throws IOException {
return new MyHTTPConduit(settings, f, b, localInfo, target);
}
MyHTTPConduit extends URLConnectionHTTPConduit
To handle SSL certificates.
TLSClientParameters parameters = new TLSClientParameters();
parameters.setDisableCNCheck(settings.isTurnOffHostVerifier());
if (settings.isIgnoreServerCertificate()) {
parameters.setTrustManagers(new TrustManager[] { new TrustAllCertsTrustManager() });
} else {
TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
factory.init(settings.getTrustStore());
parameters.setTrustManagers(factory.getTrustManagers());
}
this.setTlsClientParameters(parameters);
TrustAllCertsTrustManager class
private class TrustAllCertsTrustManager implements X509TrustManager {
#Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
To handle proxy.
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setProxyServer(proxy.getHostName());
httpClientPolicy.setProxyServerPort(proxy.getPort());
this.setClient(httpClientPolicy);
There are some examples here: http://cxf.apache.org/docs/client-http-transport-including-ssl-support.html

injecting Session bean from another session bean in JBoss 7.1

I am not able to inject a SLSB in another SLSB. Actually created 3 projects
1) created a EJB project with an MDB
2) created a EJB project with a stateless session bean for posting the message
3) created a EJB project with a stateless session bean for injecting the above session bean
But while injecting I am not able to inject the EJB it is returning null
the code is as below
1) MDB:
#MessageDriven(
activationConfig = {
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(propertyName = "destination", propertyValue = "activemq/queue/TestQueue"),
#ActivationConfigProperty(propertyName="acknowledgeMode", propertyValue="Auto-acknowledge")
})
#ResourceAdapter("activemq-ra.rar")
public class ConsumerMDB implements MessageListener {
public void onMessage(Message message) {
try {
System.out.println("Queue: Received a TextMessage at " + new Date());
TextMessage msg = (TextMessage) message;
System.out.println("Message is : " + msg.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
2) Session Bean 1
package com.springboard.session;
import javax.annotation.Resource;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
#Stateless
#LocalBean
public class ProducerSession implements ProducerSessionLocal {
#Resource(mappedName="java:jboss/activemq/QueueConnectionFactory")
public static QueueConnectionFactory factory;
#Resource(mappedName = "java:jboss/activemq/queue/TestQueue")
public static Queue queue;
#Override
public void sendMessage(String msg) {
System.out.println("****************Entering into method********************");
try {
System.out.println(queue.getQueueName());
QueueConnection qConnection = factory.createQueueConnection();
QueueSession qSession = qConnection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
TextMessage message = qSession.createTextMessage();
message.setText(msg);
QueueSender qSender = qSession.createSender(queue);
qSender.send(message);
qSender.close();
qSession.close();
qConnection.close();
} catch (JMSException e) {
e.printStackTrace();
}
System.out.println("****************Exiting into method********************");
}
}
and the interface is
package com.springboard.session;
import javax.ejb.Local;
#Local
public interface ProducerSessionLocal {
public void sendMessage(String msg);
}
3) Second session bean to inject the first session
#Stateless
public class TestProducerLocalBean implements TestProducerLocalBeanLocal {
#EJB(mappedName = "java:global/ProducerSessionActiveMQ/ProducerSession!com.springboard.session.ProducerSessionLocal")
public ProducerSessionLocal producer;
public TestProducerLocalBean() {
System.out.println("*************Testing Producer****************");
if(producer!=null){
producer.sendMessage("This Message is from SessionBean to Session Bean to MDB");
}
else{
System.out.println("EJB is null");
}
System.out.println("**********End************************");
}
#Override
public void messageSend(String msg) {
// TODO Auto-generated method stub
}
and for testing purpose used a class
import javax.ejb.EJB;
import com.springboard.session.test.TestProducerLocalBean;
public class testEJB {
#EJB
public static TestProducerLocalBean local =new TestProducerLocalBean();
public static void main(String[] args) {
}
}
At producer EJB always retuns null. With using servlet to inject ProducerSession i am able to do it. but injecting with another EJB i not able to get it.
Could any one please help me out what i am missing
Thanks in advance
It's incorrect to use initialization ... = new Xyz() when using injection because initialization of those fields is the responsibility of the container. You probably attempted that because you noticed that the field was null, and that's because injection (including #EJB) is not supported in the main class unless you use an application client container.

Resources