Showing posts with label JMS. Show all posts
Showing posts with label JMS. Show all posts

Friday, April 27, 2012

Configuring SAF agent

Below are the steps on how to create a SAF agent with file persistent store that receives messages from a publisher and forwards to another JMS server configured with JDBC persistent store.
Create two Domain1 and Domain2. Domain1 will be configured with SAF agent where as Domain2 will be configured with destinations where the consumer will listen to receive and process messages.
Domain2 configuration
  • Create JDBC data store
  • Create Persistent store based on the above JDBC data source
  • Create a new JMS server based on this JDBC persistent store
  • Create a new JMS module
  • Create a new Subdeployment for this JMS module and choose the JMS server created above
  • Create a new Connection factory
  • Create a new Queue and configure this to use the subdeployment
Domain1 configuration
  1. Create File based persistent store
  2. Create a new JMS server based on this JDBC persistent store
  3. Create a new Store-And-Forward agent.
    1. Since we are using JMS, this can only be a "Send-only" agent. 
    2. Also make sure "Logging enabled" option is selected. This allows the message to be logged in the server log file
  4. Create a new JMS module
  5. Create "Remote SAF Context" resource
    1. select the name of the remote SAF context
    2. provide the URL context for the SAF agent to login. This will be pointing to domain2 we created above.
    3. provide the credentials to logon to the aboe domain
  6. Create "SAF Error Handling" resource
    1. choose the name
    2. set Message Handling Policy to "Always-forward" since we are neither interested in discarding any messages nor re-directing them to error destination
  7. Create a new Connection factory
  8. Create a new "SAF Imported Destinations" resource in the JMS module
    1. select Remote SAF Context created above
    2. select SAF Error Handling resource created in previous step
  9. After creating the "SAF Imported Destinations" and saving the configuration, create required SAF destinations for the remote destinations
    1. create a new Queue
    2. choose Queue name
    3. choose Remote JNDI name. This will be the destination JNDI name configured in Domain2
    4. Save the Queue
    5. Select the Queue and provide "Local JNDI Name". This will be used by the publisher to publish any messages to this destination
This should configure the SAF agent to forward the messages successfully to the remote destinations. Now we can publish a message to the SAF destination and consume messages on the remote destination.

.

Wednesday, April 18, 2012

JMS File Store over JDBC Store

Weblogic JMS supports JDBC Store and Fle Store for persistence. Middleware uses JMS Distributed Queue backed by a JDBC store. This has led to some issues related to the corruption & crash of the Persistent store.

Problem faced:

There were a few instances of JDBC Persistent store crashes, due to the inability to connect to the JDBC store DB server. Either the persistent store was corrupted (meaning the store's DB tables had to be purged & the JMS restarted to bring the JMS back in action) or the JDBC Persistent store just crashed (required a JMS server restart for normal functioning) . Many messages were lost as a result of these issues and the reliability was compromised.

Issues & Impacts

  • All messages in the store were lost since the table had to be purged inorder to recover.
  • All incoming messages during the failure period were lost since the JMS was not in a state to receive incoming messages (in TRANSACTION_SEND state).
  • The messages consumed by the listener (during the crash period) could not be committed or rolled back (in TRANSACTION_RECD state) were also lost after a restart. In this case, if the message was supposed to rollback, it was not.
  • A restart was always required for the JMS server to funtion.

All this behavior were also simulated in the lab and confirmed.

In a nutshell, eventhough the JDBC store is more scalable - the reliability is compromised due to the Persistent store crashes. The database connectivity was not very reliable / high (due to DB unavailability & network connectivity). We used Oracle RAC (for high availability, and still the persistent store crashed - did not failover to the other RAC node). This could be a RAC related issue too. So, based on these behavioral aspects - JDBC store seems less reliable.

Alternate approaches tried in the lab:

  • Using a SAF agent with a JDBC persistent store: We were able to get this configuration working. This forces the SAF agent & the actual JMS to be on different servers. Also, SAF did not seem to be a right fit for this use case since the caller OSB and JMS are on the same Weblogic Domain/Server. This approach may still fail when a listener tries to commit or rollback during the JMS Persistent store crash period.
  • Use a JMS File Store for the Distributed Queue: The File Store seems to be more Reliable based on the trends seen so far. Since the File store seems more reliable, the Issues & Impacts mentioned above seems alleviated / negligible. Scalability could be an issue compared to the JDBC store - however the current file system configuration should support the expected volume in the near future.

Weblogic documentation on File Store vs JDBC Store:

http://download.oracle.com/docs/cd/E12840_01/wls/docs103/config_wls/store.html

Comparing File Stores and JDBC Stores

The following are some similarities and differences between file stores and JDBC stores:

  • The default persistent store can only be a file store. Therefore, a JDBC store cannot be used as a default persistent store.
  • The transaction log (TLOG) can only be stored in a default store.
  • Both have the same transaction semantics and guarantees. As with JDBC store writes, file store writes are guaranteed to be persisted to disk and are not simply left in an intermediate (that is, unsafe) cache.
  • Both have the same application interface (no difference in application code).
  • All things being equal, file stores generally offer better throughput than a JDBC store. | Note: | If a database is running on high-end hardware with very fast disks, and WebLogic Server is running on slower hardware or with slower disks, then you may get better performance from the JDBC store. |
  • File stores are generally easier to configure and administer, and do not require that WebLogic subsystems depend on any external component.
  • File stores generate no network traffic; whereas, JDBC stores will generate network traffic if the database is on a different machine from WebLogic Server.
  • JDBC stores may make it easier to handle failure recovery since the JDBC interface can access the database from any machine on the same network. With the file store, the disk must be shared or migrated.
Conclusion:
The solution can vary based on the infrastructure and needs of the project. For our project File store was suggested, so that the reliability can be higher.

From a monitoring perspective, there should be a disk space alert if the file system disk space reaches 75% limit.

Tuesday, June 8, 2010

Send Text Message To JMS Queue - Spring

Since I am working on Spring these days, I would post more on Spring as I have realised that Spring is the most comprehansive and more developer friendly framework among all the available frameworks in Java programming language.

Below is a class (the full code infact) that is useful to publish a text mesage into a JMS queue. Note that it use the Spring JmsTemplate. The configuration of which is given after the code snippet.


import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

/**
* Class to send JMS through spring jms template
*
* @author Darel
*
*/
public class JMSSender {
private JmsTemplate jmsTemplate;

public JmsTemplate getJmsTemplate() {
return jmsTemplate;
}

public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}

/**
* send JMS to JMS server
*
* @param queueName
* JMS queue name
* @param msg
* Queue object to be sent
*/

public void sendMesage(String queueName, final String msg) {
jmsTemplate.send(queueName, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {

return session.createTextMessage(msg);

}
});
}

}


Since this now a JMS client, we need the configuration in the application context file of Spring. The configuration is as below.


<!-- ************* JMS Client configuration ************************* -->
<bean id="jmsSender" class="com.mycompany.proj.service.util.JMSSender">
<property name="jmsTemplate">
<ref bean="queueTemplate" />
</property>
</bean>
<bean id="queueTemplate"
class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref bean="queueConnectionFactory" />
</property>
<property name="destinationResolver">
<ref bean="jmsDestinationResolver" />
</property>


</bean>
<bean id="queueConnectionFactory"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="permissionJndiTemplate" />
</property>
<property name="jndiName">
<value>${jms.connectionFactory}</value>
</property>
</bean>
<bean id="jmsDestinationResolver"
class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate">
<ref bean="permissionJndiTemplate" />
</property>
<property name="cache">
<value>true</value>
</property>
</bean>
<bean id="permissionJndiTemplate"
class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">
weblogic.jndi.WLInitialContextFactory
</prop>
<prop key="java.naming.provider.url">
${jms.provider.url}
</prop>
<prop key="java.naming.security.authentication">
${jms.authentication.type}
</prop>
<prop key="java.naming.security.principal">
${jms.security.principal}
</prop>
<prop key="java.naming.security.credentials">
${jms.security.credentials}
</prop>
</props>
</property>
</bean>


The values have $(...) which means that the value is got from the properties file. You can also hardcode the values if you do not have a properties file.

The above should be enough to publish a text message to the JMS queue. If you would need to publish a object. You can use the createObjectMessage method instead of createTextMessage.

You may also publidh a SOAP message into the JMS queue using this client. You will have to write the soap message object to a out stream and convert that to a String. The example is shown below.

//Here I am assuming that you have a method to create a SOAP message
SOAPMessage soapMessage = getSoapMessage();

ByteArrayOutputStream out = new ByteArrayOutputStream();

soapMessage.writeTo(out);

jmsSender.sendMesage(queueName, out.toString());