Now that we have a secure queue (from the prevous post), let's leverage that from an MDB.
The MDB will simply consume the messages - the only logic our onMessage() requires is -
public void onMessage(Message message) {
try{
if (message instanceof TextMessage) {
TextMessage txtMsg = (TextMessage) message;
System.out.println("**** Message: " + txtMsg.getText());
}
}
catch(Exception e){
e.printStackTrace();
}
Step 1. - Create a new project in JDeveloper
Step 2. - Create a new MDB in the project
-- File --> New --> EJB --> Message Driven Bean --> 2.1
Step 3 - Set up security
-- run-as identity is specified in the ejb-jar.xml
-- security-role is specified in the ejb-jar.xml
-- Map run-as identity to principal-name in weblogic-ejb-jar.xml
Step 3.1 - ejb-jar.xml
-- These properties can be set via the properties palette (Right mouse click on the bean and select Properties)
Step 3.2. weblogic-ejb-jar.xml
-- These properties can also be set via the palette
Step 4. Deploy
Step 5. Test
-- Check WLS log for the output message
-- Change principal-name in weblogic-ejb-jar.xml to weblogic
-- Re-test
Thursday, May 19, 2011
Wednesday, May 18, 2011
Weblogic 11g - securing JMS artifacts
Scenario -
I need to secure a JMS Queue.
Only the members of the JMSUSERGROUP (e.g.JMSUSER) -
should be able to access it.
Create JMS Server/JMS Module/Connection Factory/ Queue
Add Security Role/Policy -
Test with JMS Client
---------------------------------------------------------
public class JMSClient {
public static void main(String [] args) throws JMSException,
NamingException {
final Context ic = getInitialContext();
System.out.println("*** CONTEXT =");
final QueueConnectionFactory qcf = (QueueConnectionFactory)ic.lookup("jms/MyCF2");
// Lookup should specify the queue name that is mentioned as "mappedName" in MessageDriven Bean.
final Queue destQueue = (Queue)ic.lookup("jms/MyQueue3");
final QueueConnection connection = qcf.createQueueConnection("JMSUSER", "welcome1");
try {
final QueueSession session = connection.createQueueSession(false, 0);
final QueueSender sender = session.createSender(destQueue);
final TextMessage msg = session.createTextMessage("Hello from Galway - fans of FCN");
sender.send(msg);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
connection.close();
ic.close();
}
}
---------------------------------------------------------
Test with JMSUSER -->
Test with weblogic -->
I need to secure a JMS Queue.
Only the members of the JMSUSERGROUP (e.g.JMSUSER) -
should be able to access it.
Create JMS Server/JMS Module/Connection Factory/ Queue
Add Security Role/Policy -
Test with JMS Client
---------------------------------------------------------
public class JMSClient {
public static void main(String [] args) throws JMSException,
NamingException {
final Context ic = getInitialContext();
System.out.println("*** CONTEXT =");
final QueueConnectionFactory qcf = (QueueConnectionFactory)ic.lookup("jms/MyCF2");
// Lookup should specify the queue name that is mentioned as "mappedName" in MessageDriven Bean.
final Queue destQueue = (Queue)ic.lookup("jms/MyQueue3");
final QueueConnection connection = qcf.createQueueConnection("JMSUSER", "welcome1");
try {
final QueueSession session = connection.createQueueSession(false, 0);
final QueueSender sender = session.createSender(destQueue);
final TextMessage msg = session.createTextMessage("Hello from Galway - fans of FCN");
sender.send(msg);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
connection.close();
ic.close();
}
}
---------------------------------------------------------
Test with JMSUSER -->
Test with weblogic -->
Tuesday, May 17, 2011
Basic JMS Clustering with Weblogic 11g - standalone Queue/Service Migration
In this scenario we need to make a standalone Queue highly available.
The Queue will be targeted to JMSServer2 running on MgdServer2.
If MgdServer2 goes down then the JMSServer will be migrated to MgdServer1.
Here I strongly suggest you consult the weblogic docs to understand fully
the concepts. Here is a short extract from the aforementioned -
------------------------------------------------------------------------
In a WebLogic Server cluster, most subsystem services are hosted homogeneously on all server instances in the cluster, enabling transparent failover from one server to another. In contrast, pinned services, such as JMS-related services, the JTA Transaction Recovery Service, and user-defined singleton services are hosted on individual server instances within a cluster—for these services, the WebLogic Server migration framework supports failure recovery with service migration, as opposed to failover.
Service-level migration in WebLogic Server is the process of moving the pinned services from one server instance to a different available server instance within the cluster. Service migration is controlled by logical migratable target, which serves as a grouping of services that is hosted on only one physical server in a cluster. You can select a migratable target in place of a server or cluster when targeting certain pinned services. High availability is achieved by migrating a migratable target from one clustered server to another when a problem occurs on the original server. You can also manually migrate a migratable target for scheduled maintenance or you can configure the migratable target for automatic migration.
------------------------------------------------------------------------
Leading on from the previous post...
Create a second JMS Server - JMSServer2 and target to MgdServer2(Migratable)
Step 1 - Create a new JMS module /Connection Factory and Queue
Subdeployment targeted as follows -
Create the connection Factory and target as follows -
Create the Queue, target to JMSServer2
Test -
------------------------------------------
public static void main(String [] args) throws JMSException,
NamingException {
final Context ic = getInitialContext();
System.out.println("*** CONTEXT =");
final QueueConnectionFactory qcf = (QueueConnectionFactory)ic.lookup("jms/MyCF2");
// Lookup should specify the queue name that is mentioned as "mappedName" in MessageDriven Bean.
final Queue destQueue = (Queue)ic.lookup("jms/MyQueue2");
ic.close();
final QueueConnection connection = qcf.createQueueConnection();
try {
final QueueSession session = connection.createQueueSession(false, 0);
final QueueSender sender = session.createSender(destQueue);
final TextMessage msg = session.createTextMessage("Hello from Dublin - fans of FCN");
sender.send(msg);
-------------------------------------------
View message in the WLS console
We can also enable logging on the Queue
Re-test and view logs
Now stop MgdServer2 and re-test
View logs under MgdServer1
The Queue will be targeted to JMSServer2 running on MgdServer2.
If MgdServer2 goes down then the JMSServer will be migrated to MgdServer1.
Here I strongly suggest you consult the weblogic docs to understand fully
the concepts. Here is a short extract from the aforementioned -
------------------------------------------------------------------------
In a WebLogic Server cluster, most subsystem services are hosted homogeneously on all server instances in the cluster, enabling transparent failover from one server to another. In contrast, pinned services, such as JMS-related services, the JTA Transaction Recovery Service, and user-defined singleton services are hosted on individual server instances within a cluster—for these services, the WebLogic Server migration framework supports failure recovery with service migration, as opposed to failover.
Service-level migration in WebLogic Server is the process of moving the pinned services from one server instance to a different available server instance within the cluster. Service migration is controlled by logical migratable target, which serves as a grouping of services that is hosted on only one physical server in a cluster. You can select a migratable target in place of a server or cluster when targeting certain pinned services. High availability is achieved by migrating a migratable target from one clustered server to another when a problem occurs on the original server. You can also manually migrate a migratable target for scheduled maintenance or you can configure the migratable target for automatic migration.
------------------------------------------------------------------------
Leading on from the previous post...
Create a second JMS Server - JMSServer2 and target to MgdServer2(Migratable)
Step 1 - Create a new JMS module /Connection Factory and Queue
Subdeployment targeted as follows -
Create the connection Factory and target as follows -
Create the Queue, target to JMSServer2
Test -
------------------------------------------
public static void main(String [] args) throws JMSException,
NamingException {
final Context ic = getInitialContext();
System.out.println("*** CONTEXT =");
final QueueConnectionFactory qcf = (QueueConnectionFactory)ic.lookup("jms/MyCF2");
// Lookup should specify the queue name that is mentioned as "mappedName" in MessageDriven Bean.
final Queue destQueue = (Queue)ic.lookup("jms/MyQueue2");
ic.close();
final QueueConnection connection = qcf.createQueueConnection();
try {
final QueueSession session = connection.createQueueSession(false, 0);
final QueueSender sender = session.createSender(destQueue);
final TextMessage msg = session.createTextMessage("Hello from Dublin - fans of FCN");
sender.send(msg);
-------------------------------------------
View message in the WLS console
We can also enable logging on the Queue
Re-test and view logs
Now stop MgdServer2 and re-test
View logs under MgdServer1
Basic JMS Clustering with Weblogic 11g - Uniform distributed destination
JMS is an integral part of many SOA/Integration projects.
Like any other resource, we want scalability and reliability for our JMS artifacts.
So here is a simple example based on the following simple WLS cluster I've set up
Example 1: Using a UDD(Uniform distributed destination)
Thanks to my colleague Santosh for his support here.
UDDs make sense for both reliability and scalability. Essentially the UDD Queue
will be deployed to my cluster and thus available on both of my managed servers.
Step 1 -Create a JMS Server (JMSServer1)
-- FileStore= JMSFileStore1
-- Target= MgdServer1(Migratable)
Step 2 - Create a JMS System Module for the ConnectionFactory & UDD Queue (JMSModuleCluster)
Step 4 - Test with a JMS Client
--------------------------------------------------
package jmsclient;
import java.util.Hashtable;
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;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class JMSClient {
public static void main(String [] args) throws JMSException,
NamingException {
final Context ic = getInitialContext();
System.out.println("*** CONTEXT =");
final QueueConnectionFactory qcf = (QueueConnectionFactory)ic.lookup("jms/MyCF");
// Lookup should specify the queue name that is mentioned as "mappedName" in MessageDriven Bean.
final Queue destQueue = (Queue)ic.lookup("jms/MyDistQueue");
ic.close();
final QueueConnection connection = qcf.createQueueConnection();
try {
final QueueSession session = connection.createQueueSession(false, 0);
final QueueSender sender = session.createSender(destQueue);
final TextMessage msg = session.createTextMessage("Hello from Lichtenau - fans of FCN");
sender.send(msg);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
connection.close();
}
}
private static Context getInitialContext() throws NamingException {
Hashtable env = new Hashtable();
// Add InitialContext property assignments here.
env.put( Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory" );
// Note that by default WebLogic server is not created with security, so credentials are not needed.
// TODO: Verify the server address and port number
env.put(Context.PROVIDER_URL, "t3://localhost:7003,localhost:7004");
env.put(Context.SECURITY_PRINCIPAL, "weblogic");
env.put(Context.SECURITY_CREDENTIALS, "welcome1");
return new InitialContext( env );
}
}
------------------------------------------------------------
You can stop any of the 2 managed servers and re-test.
The Queue is alway available.
Like any other resource, we want scalability and reliability for our JMS artifacts.
So here is a simple example based on the following simple WLS cluster I've set up
Example 1: Using a UDD(Uniform distributed destination)
Thanks to my colleague Santosh for his support here.
UDDs make sense for both reliability and scalability. Essentially the UDD Queue
will be deployed to my cluster and thus available on both of my managed servers.
Step 1 -Create a JMS Server (JMSServer1)
-- FileStore= JMSFileStore1
-- Target= MgdServer1(Migratable)
Step 2 - Create a JMS System Module for the ConnectionFactory & UDD Queue (JMSModuleCluster)
Step 4 - Test with a JMS Client
--------------------------------------------------
package jmsclient;
import java.util.Hashtable;
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;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class JMSClient {
public static void main(String [] args) throws JMSException,
NamingException {
final Context ic = getInitialContext();
System.out.println("*** CONTEXT =");
final QueueConnectionFactory qcf = (QueueConnectionFactory)ic.lookup("jms/MyCF");
// Lookup should specify the queue name that is mentioned as "mappedName" in MessageDriven Bean.
final Queue destQueue = (Queue)ic.lookup("jms/MyDistQueue");
ic.close();
final QueueConnection connection = qcf.createQueueConnection();
try {
final QueueSession session = connection.createQueueSession(false, 0);
final QueueSender sender = session.createSender(destQueue);
final TextMessage msg = session.createTextMessage("Hello from Lichtenau - fans of FCN");
sender.send(msg);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
connection.close();
}
}
private static Context getInitialContext() throws NamingException {
Hashtable env = new Hashtable();
// Add InitialContext property assignments here.
env.put( Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory" );
// Note that by default WebLogic server is not created with security, so credentials are not needed.
// TODO: Verify the server address and port number
env.put(Context.PROVIDER_URL, "t3://localhost:7003,localhost:7004");
env.put(Context.SECURITY_PRINCIPAL, "weblogic");
env.put(Context.SECURITY_CREDENTIALS, "welcome1");
return new InitialContext( env );
}
}
------------------------------------------------------------
You can stop any of the 2 managed servers and re-test.
The Queue is alway available.
Tuesday, May 10, 2011
SOA Suite 11.1.1.5.0 now available
software
http://www.oracle.com/technetwork/middleware/soasuite/downloads/index.html
docs
http://www.oracle.com/technetwork/middleware/soasuite/documentation/index.html#111150
http://www.oracle.com/technetwork/middleware/soasuite/downloads/index.html
docs
http://www.oracle.com/technetwork/middleware/soasuite/documentation/index.html#111150
Monday, May 9, 2011
EDN via PL/SQL
Scenario:
Raise an event on an insert to a DB table. Event is then consumed by a SOA composite.
In this case, this is a viable alternative to using a DB adapter(polling) as our table, in this scenario, only gets a couple of inserts per day.
XSD used
Create a sample ORDERS table in SCOTT's schema
Create a SOA app/project in JDev
Create an Event Definition in the project
Import the XSD
Here is the edl file
Create a PLSQL stored procedure that will call the following –
Our parameters, taken in part from the edl above, are as follows –
NAMESPACE – http://www.example.org
LOCAL_NAME - anything you like e.g. Our Event Name - NewOrder
PAYLOAD – This is our order
PRIORITY – DEFAULT is 5 so we don’t need to enter this.
However there is some “wrapper” overhead.
eb:business-event xmlns:eb=http://oracle.com/fabric/businessEvent
This is the default, so no need to change.
xmlns:ob="http://schemas.oracle.com/events/edl/NewOrder">
Set to the namespace from our edl.
eb:name ob:NewOrder
This is set to the EventName e.g. NewOrder
eb:content
Contains the actual payload i.e. our Order
Test the PLSQL
There should be an entry in the dev_soainfra.EDN_EVENT_QUEUE_TABLE
Now back to the SOA app...
Create a Mediator that subscribes to the event
Then create a File Adapter(Write) using the same xsd
Deploy and test
- You can execute the procedure directly in JDev
- View the result in em
View the output file
Now we need to include the PLSQL code in the POST-INSERT trigger logic.
Create a POST-Insert trigger on the nc_orders table
Insert a row
Raise an event on an insert to a DB table. Event is then consumed by a SOA composite.
In this case, this is a viable alternative to using a DB adapter(polling) as our table, in this scenario, only gets a couple of inserts per day.
XSD used
Create a sample ORDERS table in SCOTT's schema
Create a SOA app/project in JDev
Create an Event Definition in the project
Import the XSD
Here is the edl file
Create a PLSQL stored procedure that will call the following –
Our parameters, taken in part from the edl above, are as follows –
NAMESPACE – http://www.example.org
LOCAL_NAME - anything you like e.g. Our Event Name - NewOrder
PAYLOAD – This is our order
PRIORITY – DEFAULT is 5 so we don’t need to enter this.
However there is some “wrapper” overhead.
eb:business-event xmlns:eb=http://oracle.com/fabric/businessEvent
This is the default, so no need to change.
xmlns:ob="http://schemas.oracle.com/events/edl/NewOrder">
Set to the namespace from our edl.
eb:name ob:NewOrder
This is set to the EventName e.g. NewOrder
eb:content
Contains the actual payload i.e. our Order
Test the PLSQL
There should be an entry in the dev_soainfra.EDN_EVENT_QUEUE_TABLE
Now back to the SOA app...
Create a Mediator that subscribes to the event
Then create a File Adapter(Write) using the same xsd
Deploy and test
- You can execute the procedure directly in JDev
- View the result in em
View the output file
Now we need to include the PLSQL code in the POST-INSERT trigger logic.
Create a POST-Insert trigger on the nc_orders table
Insert a row