The necessary code to write messages to a WebLogic Server queue doesn't have to use any WebLogic specific classes, just plain regular javax.jms.*
and javax.naming.*
components.
There are some classes and interfaces provided by WebLogic that help us access WebLogic-specific features, but as they address very specialized scenarios, chances are you're not going to use them very often. They are inside the weblogic.jms.extensions
package, and you can find their Javadoc at http://docs.oracle.com/middleware/1212/wls/WLAPI/weblogic/jms/extensions/package-summary.html.
As said earlier in this chapter, the business functionality we're going to implement will act as a bridge between the partner's system and the Theater module deployed at their installations, and will receive information about new exhibition dates that must be uploaded to our module.
To accomplish this, we will create a standalone Java project named RemoteClient
and add a Java class that will read the command-line arguments that represent the new exhibition, pack them inside an Exhibition
class instance, and post it to a message queue.
The following are the steps to set up the environment that our code needs:
Java
in the Wizards text field, click on the Java Project entry, and then on the Next button.RemoteClient
as Project Name, make sure you're using JDK 1.7 in the JRE group (change it if necessary), and click on Next./$MW_HOME/wlserver/server/lib
and select the wlthint3client.jar
file.Exhibition
class, we also need to add a reference to its package, TheaterBO.jar
, in the same way. Click on the Add External JARs… button, then navigate to the location where you saved the TheaterBO.jar
file that is deployed as a shared library.As there are no specific needs regarding the message producer, we will write the code inside the main
method of our class.
com.packt.client
inside the RemoteClient project, and add a class named Enqueue
inside this package.static final String WLS_ADDRESS = "t3://localhost:7001"; static final String WLS_CTX_FACTORY = "weblogic.jndi.WLInitialContextFactory"; static final String JMS_QUEUE_FACTORY = "weblogic.jms.ConnectionFactory"; static final String JMS_QUEUE_NAME = "jms.tickets.exhibition";
Exception
, so we save a few try/catch blocks:public static void main(String args[]) throws Exception { }
Context ct; Hashtable<String, String> env = new Hashtable<>(); env.put(Context.PROVIDER_URL, WLS_ADDRESS); env.put(Context.INITIAL_CONTEXT_FACTORY, WLS_CTX_FACTORY); env.put(Context.SECURITY_PRINCIPAL, "weblogic"); env.put(Context.SECURITY_CREDENTIALS, "welcome1"); // Get a server connection ct = new InitialContext(env);
Movie
, Room
, and Exhibition
using command-line arguments as attribute values:/* * Argument sequence and format: * 0: Movie Id * 1: Room Id * 2: Exhibition date - MM.DD.YYYY * 3: Exhibition time - HHMM */ Movie movie = new Movie(); movie.setId(Integer.parseInt(args[0])); Room room = new Room(); room.setId(Integer.parseInt(args[1])); Exhibition exhibition = new Exhibition(); exhibition.setMovie(movie); exhibition.setRoom(room); exhibition.setDate(new SimpleDateFormat("MM.dd.yyyy"). parse(args[2])); exhibition.setHour(Integer.parseInt(args[3]));
javax.jms
:QueueConnectionFactory qcf; QueueConnection qc = null; QueueSession qs = null; QueueSender sender = null; Queue queue; ObjectMessage msg;
finally
block to close the JMS resources, as they don't support Java 7's try-with-resources feature yet:try { // Set up JMS components qcf = (QueueConnectionFactory) ct.lookup(JMS_QUEUE_FACTORY); qc = qcf.createQueueConnection(); qs = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); // Get a handle to the JMS queue queue = (javax.jms.Queue) ct.lookup(JMS_QUEUE_NAME); // Create ... msg = qs.createObjectMessage(); msg.setObject(exhibition); // ... and send the message sender = qs.createSender(queue); sender.send(msg); } catch(Exception e) { e.printStackTrace(); } finally { // Doesn't support try-with-resources yet... try { sender.close(); } catch (Exception e) { } try { qc.close(); } catch (Exception e) { } try { qs.close(); } catch (Exception e) { } try { ct.close(); } catch (Exception e) { } }
You will see an error mark at the top of the class. If you hover the mouse over it, the message The type javax.persistence.TemporalType cannot be resolved. It is indirectly referenced from required .class files will pop up. This class is used by the TheaterBO
package, but as we aren't dealing with the persistence layer here, we can ignore the error. Compilation and execution will run as expected.
The code is ready to generate messages. Let's post a few entries!
We're going to execute the client from Eclipse, so we need to create a run configuration:
Enqueue
.5 1 01.01.2013 1400
sequence in the Program arguments box.As we still don't have a consumer attached to the queue, you can check it and see that there are messages waiting for delivery:
Notice the buttons just above the message table. Other than checking the messages already in the queue, you can:
As we post object messages, if you click on the message ID, a screen with the warning Unable to view message, reason = java.class.ClassNotFoundException: com.packt.domain.theater.Exhibition shows up. You must add the class' package to WebLogic's classpath, and the easiest way to accomplish this is to drop the TheaterBO.jar
file for our example into the /lib
folder of the target domain, $ DOMAIN_HOME/tickets
, and restart the server.
This is how the detail screen should look like if you do this:
When you already have a consumer that is attached to a queue and needs to check the messages coming through it, you can stop the queue's consumption. Also, you can pause the production and/or insertion of messages of a given queue, for instance, to avoid an overload situation. Let's define these administration-related terms:
These pauses—production, insertion, and consumption—are held until the server goes down. If you restart a WebLogic node, all states are set back to enabled, or more specifically, to the default value for each state, which you can configure in the Configuration tab, the General inner tab, and the Advanced group of a destination component.
Here's the screen where we can pause or resume the production and/or consumption of our queue:
Now that we confirmed that there's a message or two waiting in the queue, let's code a bean to consume them.