Thursday, January 19, 2012

Servicemix

Initial links for ServiceMix 4...
The documentation isn't good, often it's not clear if ServiceMix 3 or 4 is being referred to.
So use the FUSE documentation at http://fusesource.com/products/enterprise-servicemix/, it's better, and the FUSE version of ServiceMix is really the same as the pure Apache version, but with the potential to buy support and consultancy alongside.
A couple of popular links to get going:
This question on stackoverflow reflects what I found - the documentation is out of date: http://stackoverflow.com/questions/3501581/tutorial-for-servicemix-4-2
I think I'll be writing more about ServiceMix in the next few months...

Labels:

Thursday, September 08, 2011

Eclipse VM settings reminder!

You need to make sure your Eclipse is running with a JDK, not just a JRE
eclipse.ini needs something like the following:


-startup
plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.100.v20110502
-product
org.eclipse.epp.package.jee.product
--launcher.defaultAction
openFile
--launcher.XXMaxPermSize
1024M
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
1024m
--launcher.defaultAction
openFile
-vm
C:\Program Files\Java\jdk1.7.0\bin
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms256m
-Xmx1024m

Note that the path to the JDK must be the full path to the executable (i.e. include the /bin), and the path must be on a NEW LINE after the "-vm".
Don't forget to adjust your PermGen and Heap sizes whilst you're about it - see above for the relevant settings...

Wednesday, April 20, 2011

Weblogic JMS and SAF - notes

Introduction

This provides some info and background information needed to configure and operate Weblogic messaging (partly using SAF).

We start with a discussion of how Weblogic JMS and SAF (Store-And-Forward) will be used to enable this traffic, including its features and limitations. Then the specific configuration steps are given, including things to note and watch out for which were learnt during the Proof Of Concept phase. After that, there is some information about how to operate and troubleshoot the connection, plus whatever extra information might be useful.

I have put the actual configuration steps which need to be executed via the Weblogic console (as opposed to the discussion and background information etc.) in these green boxes.
NB 1: each update on the Weblogic console is enclosed within “Lock & Edit” and “Activate Changes”, to ensure that each one is applied successfully before proceeding.

NB 2: be careful as some of the resource names are long and split up over two lines in this document!

NB 3: bear in mind a useful and comprehensible naming convention for the Weblogic JMS/SAF resources! e.g.

-ComponentName

(This is because if they all start with the same ComponentName, they kind of look the same, if you happen to only have browser width only able to show the first few characters.)

Environment

The aim here is to get a Weblogic domain talking to another Weblogic domain for the purposes of exchanging JMS traffic for messaging requirements. This involves setting up Weblogic JMS and SAF (Store-And-Forward) configurations to provide access to JMS Destinations on each domain. If you are using OSB/ALSB, ALSB components (proxy and business services) will also have to be written which will make use of the JMS/SAF configuration, so that needs to be in place before the ALSB components will work.

The Solution

The capability to send JMS messages between the two domains will be provided using Weblogic JMS and its SAF (Store And Forward) feature. This feature allows JMS messages to be sent from one domain to another, being queued in the originating domain should the destination not be available. This is achieved by configuring a real Weblogic JMS queue in the destination domain, and “importing” that destination into the originating domain using the SAF resources. The Message Producing component is therefore sending to an imported representation of a real, remote queue. Message Consumers will consume from the “real” JMS destination and be unaware of it being anything to do with SAF.

Configuration

Domain Trust

In order to exchange messages via SAF, the two domains involved will need to “trust” each other. This means they need to share the same domain credential. We will need to agree with the other side the domain credential to use, and both sides will need to set it on their domain. See this page for explanation: http://download.oracle.com/docs/cd/E13222_01/wls/docs92/ConsoleHelp/taskhelp/security/EnableTrustBetweenDomains.html

Extract from this page reproduced here:

“Trust between domains is established so that principals in a Subject from one WebLogic Server domain are accepted as principals in another domain. When this feature is enabled, identity is passed between WebLogic Server domains over an RMI connection without requiring authentication in the second domain. When inter-domain trust is enabled, transactions can commit across domains. A trust relationship is established when the Domain Credential for one domain matches the Domain Credential for another domain.

By default, the Domain Credential is randomly generated and therefore, no two domains will have the same Domain Credential. If you want two WebLogic Server domains to interoperate, you need to replace the generated credential with a credential you select, and set the same credential in each of the domains.”

1. In Weblogic console, go to: Home -> Domain -> Security (tab)

2. Click “Lock & Edit” button

3. Click “Advanced”

4. Update “Credential” and “Confirm Credential” to be the agreed value

5. Click “Activate Changes” button

6. Restart the entire Weblogic domain (all servers, inluding the Admin server)

JMS Server

Do we actually need any extra JMS Servers? A suitable JMS server or servers (for the cluster) may already be available. This implies that suitable File Stores are also already set up, which are used by default.

JMS Module

This JMS Module groups all the configuration related to the SAF communication into one place. Is a good idea to group these configs together or you will lose stuff.

1. In Weblogic console, go to: Home -> Messaging -> JMS Modules

2. Click “Lock & Edit” button

3. Add new Module “JMSModule-ThisComponent”

4. Target the module to the local cluster

5. Save

6. Click “Activate Changes” button

JMS Subdeployment

This is to group together the components which need to be deployed together

1. In Weblogic console, go to: Home -> Messaging -> JMS Modules -> JMSModule-ThisComponent

2. Click on “Subdeployments” tab

3. Click “Lock & Edit” button

4. Add new Subdeployment “JMSSubDep-ThisComponent”

5. Target the subdeployment to the local cluster

6. Click “Activate Changes” button

JMS Connection Factories

Define the connection factories needed to support the message producers/consumers – or use the default ones...

- One to support the outbound producer

- One to support the inbound consumer

1. In Weblogic console, go to: Home -> Messaging -> JMS Modules -> JMSModule-ThisComponent

2. Click “Lock & Edit” button

3. Add new Connection Factory:
choose a sensible name!
Set JNDI name the same as the resource name
Accept all defaults and set Subdeployment to “JMSSubDep-ThisComponent”
Save

4. Add new Connection Factory:
Choose a sensible name!
Set JNDI name the same as the resource name
Accept all defaults and set Subdeployment to “JMSSubDep-ThisComponent”
Save

5. Add new Connection Factory:
Choose a sensible name!
Set JNDI name the same as the resource name
Accept all defaults (except below) and set Subdeployment to “JMSSubDep-ThisComponent”
Go to “Default Delivery” tab. Set “Default Time-to-Deliver” to 600000 (this would be a separate connection factory in case you wanted to have a retry facility which would put messages back onto the queue, but with a delay, to stop an immediate retry...)
Save

6. Click “Activate Changes” button

JMS Queues

This defines the JMS Queue that will support incoming messages. Note that we don’t define a queue for the outbound messages, this will be handled via an imported SAF Destination, which we’ll come to later.

The queue is a Uniform Distributed Queue and has a Forward Delay option set to 10 seconds, to ensure that messages which land on a member queue which doesn’t have a consumer get automatically forwarded to another member queue which does have a consumer, if possible.

2. In Weblogic console, go to: Home -> Messaging -> JMS Modules -> JMSModule-ThisComponent

3. Click “Lock & Edit” button

4. Add new Distributed Queue:
ThisComponent.QueueName
Set JNDI name the same as the resource name
Accept all defaults
Click on “Advanced Targeting” and set Subdeployment to “JMSSubDep-ThisComponent”.
Save
Re-enter the newly created Queue. On the Configuration General tab, set “Forward Delay” to 10.

5. Click “Activate Changes” button

Weblogic Store-And-Forward (SAF) Configuration

This contains the configuration which is needed to support the cross-domain JMS traffic for the outbound messages. Note that we don’t configure here anything to do with the inbound messages. They are dealt with in the previous section, and the idea is that the other side will have a corresponding imported SAF Destination on their side to support it.

To configure SAF, you first need a Store-and-Forward agent deployed on the cluster. Then you can import destinations which reside on remote Weblogic instances. This involves adding a “SAF Remote Context” which will instruct SAF to point to the remote Weblogic cluster at the URL provided by the other side. A “SAF Error Handling” resource is also added which determines what to do when problems occur. Then a “SAF Imported Destinations” resource is added to specify which queues should be imported from the Remote Context. All these resources are bundled up in the JMS Module we created earlier.

1. See Implementation Script document for definitive version of these steps!

2. In Weblogic console, go to: Home -> Messaging -> Store-and-Forward Agents

3. Click “Lock & Edit” button

4. Add new Store-and-Forward Agent “SAFAgent-ThisComponent”
Accept all defaults
Target to the local cluster
Save

5. Go to: Home -> Messaging -> JMS Modules -> JMSModule-ThisComponent so that you can add new resources to the module

6. Add new “SAF Error Handling” resource named “ErrorHandling-ThisComponent”
Change Message Handling Policy to “Log”
Save

7. Add new “Remote SAF Context” resource named “RemoteSAFContext-ThisComponent”
Set URL to that of the appropriate remote system for this environment (e.g. “t3://remotesystem:7001”).
Set the remote credentials (User Name and Password) which will be used
Accept other defaults
Save

8. Add new “SAF Imported Destinations” resource named “SAFImportedDestinations-ThisComponent”
set Remote SAF Context to “RemoteSAFContext-ThisComponent”
set SAF Error Handling to “ErrorHandling-ThisComponent”
Target to the “JMSSubDep-ThisComponent” subdeployment
Save

9. Re-enter the newly created “SAFImportedDestinations-ThisComponent” resource
Click on Configuration tab, Queues sub-tab
Add new SAF Queue with name of the real remote queue where we should be putting the outbound messages. See table below.
Remote JNDI name should be the same
Finish

10. Click “Activate Changes” button

11. It may be advisable to restart the domain to ensure everything is reinitialized with the new configuration and there aren’t any old bits and pieces hanging around. Weblogic does sometimes throw confusing errors which miraculously go away after a restart.

Post-configuration checks

After the configuration above is done, and everything’s up and running, we should be in a position to see messages flowing across the domains, assuming you’ve got some way of creating test messages and JMS producers onto the SAF queue... (or consumers onto the real inbound queue).

If you’re going via OSB/ALSB you could use a Proxy service to create test messages...Create a test message with the proxy and check that it goes out and appears in the safagent logs (assuming you’ve switched on the message logging for the SAF destinations).

For the inbound messages, we need to have some sort of harness which simulates the remote systems (unless we have connectivity to a real one), and puts a suitable message onto an imported SAF queue, which will forward it to the REAL queue which has been added (as part of the above script) to our domain, and in turn will get picked up by whatever is listening/consuming that queue.

There is a bit of test Java code (QueueEchoer/QueueSender) from the POC stage to help with simulating the message flow, which could be set up to talk to whatever domains we have available. There are plenty of sample JMS Message Producer/Consumer java classes to try out on t’internet.

To point a producer to a SAF queue, you need to point it at the cluster address that the Destination (assuming it’s a Distributed Destination) is on. You can get the cluster address from the Weblogic console: Log into the Weblogic console, and navigate to “Clusters”. For the active cluster, copy the “Cluster Address” This could be something like “host1:7001,host2:7001,host3:7001” if there are multiple Weblogic instances that it’s deployed to...

Environments

You will probably want to set up configurable properties for things like:

- the remote system URL

- the destination cluster address (if applicable)

- the user name and password for the SAF context

- etc.

Troubleshooting

A random collection of notes concerning possible pitfalls and things learnt about Weblogic JMS/SAF...

“ServerIdentity failed validation. Downgrading to anonymous.”

If you see this in the logs it may mean that the domains don’t trust each other. See the above section on enabling domain trust.

Firewalls

If SAF fails to connect, one thing to make sure is that any necessary ports are opened on the firewall(s).

Debug logs for SAF

To debug SAF, use the Debug tab in the Server page and enable the jms.saf.DebugJMSSAF (+DebugMessaging) options. Also you need to ensure the debug options in the server(s) Logging tabs are set to Debug at least. Then restart the server(s). Log items referring to “JMSSAF” and other JMS-related items should start appearing in the server logs (suggestion: tail –f logname.log | grep “JMSSAF”).

It may also be useful to switch on Message Logging in the JMS Queue resources themselves. These get written to a jms.message.log file in the server logs directory. SAF messages can also be logged, these appear in files in the safagents subdirectory of the server logs directory.

Patch Level

There have been various rumours of known problems with SAF on Weblogic 9, although we haven’t encountered any - yet. According to registry.xml in the BEA Weblogic folder on our Dev system, we are at the following patch level of Weblogic 9.2:

level=9.2 ServicePackLevel=1 PatchLevel=0

JMS resources not targeted properly?

Ensure “Default Targeting Enabled” isn’t ticked, and the items are deployed on the correct server, targeted to the right subdeployment, etc. Check they appear in the JNDI tree (any JNDI tree for the cluster should do, as cluster-available resources will appear in all the server-level JNDI trees).

“Server Affinity” setting

This setting is connected with load balancing and has been identified as something which needs to be switched on in the connection factories. It should be on by default, add something in the scripts to check that this is definitely the case when the connection factories are created.

Messages/SAF Agent hangs?

Apparently can happen, especially if patches aren’t in. Apart from the list of possible patches which could help with this, check the following: need to ensure the JMS destination for the business service, which will actually send to the SAF queue, has got all the cluster hosts/ports mentioned. If you just have one it maybe a problem? E.g. check outbound message producer – is it pointing to an endpoint something like “t3://host1:7210,host2:7210/ConnexFactory/SAFQueueName”...

Tuesday, March 29, 2011

Connecting JMX client to Weblogic

There is an "experimental" JMX client inside the JDK called jconsole. You can start this GUI and then enter a Remote connection address for your Weblogic server.

To enable it to connect however, you have to add the JMX options to the Weblogic startup. (See this page: http://malliktalksjava.wordpress.com/2010/08/19/enabling-jmx-port-in-weblogic/)

This involves editing your setDomainEnv.cmd script for your Weblogic domain, and adding some options:

set JAVA_OPTIONS= %JAVA_OPTIONS%
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8006
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

Then restart Weblogic. It should now be listening on port 8006 for clients.

Start jconsole, enter address in Remote tab, and Connect. You should now be able to browse MBeans. My Weblogic is running Sun Java 5, not sure if it's the same if you're running it under JRockit or something else...

Monday, March 28, 2011

WLST to get some info about a Weblogic JMS/SAF Resource...

Example script of how to get a statistic (in this case the BytesReceivedCount) from a SAF resource (queue/topic)

# Connect to Weblogic server
# NB choose right port if you want to talk to a Managed Server instead of
# the Admin server...
connect('weblogic','weblogic','t3://localhost:7003')
serverRuntime()

# For a JMS resource:
cd('/JMSRuntime/servername.jms/JMSServers/jmsservername/Destinations/JMSModuleName!jmsservername@JMSDestinationName')

# For a SAF resource:
cd('/SAFRuntime/servername.saf/Agents/SAFAgentName/RemoteEndpoints/JMSModule!SAFImportedDestinations!SAFDestinationName')

count = cmo.getBytesReceivedCount()
print 'bytes received = %d' % count

Note the serverRuntime() call which connects you to the runtime tree for the server you're interested in.

Tuesday, June 15, 2010

Oracle BPEL: Correlation sets

Useful post on correlation sets:

http://swapnil-soa.blogspot.com/2008/01/correlation-this-post-would-effort-to.html

The thing that it took me a while to realize is this. The "properties" of the correlation set are those values which are needed to correlate messages. The way to think of it is that you need to remember which instance you are going back to, like in the example of the flight request. If a flight agent fires off ten reservation requests, with a unique ID in each, then how do you tell which response has come back? You look at the ID which is returned by the flight system, and route the response to the corresponding instance. This isn't the same as putting a correlation ID into the correlationSet even before the message has gone anywhere, it's picking an ID from the message and looking for the same ID on the way back in order to know which reply has come back (and therefore which instance to use). God that was confused, the guy who wrote the above blog post puts it better.

To put it in concrete terms. If you want to correlate a message with a particular instance, when you've got three different services working togethetr, then do the following.

Here we have three services:
CallingService - this sends a message to the WorkerService, which starts up and then waits for a second message (different operation) to tell it to finish.
WorkerService - receives an incoming message from the initiate operation, then waits pending receipt of a "stop" operation message to tell it to finish. Worker service, in its contract, includes an "id" (string or integer or whatever) to correlate on.
StopService - this sends the "stop" message to the WorkerService, using the same ID in the input message which has been set up to correlate on.

The flow proceeds as follows:
1. CallingService sets up an ID of "id0001" in the message to WorkerService
2. CallingService calls "initiate" on WorkerService, with the ID (NB: no correlationSet defined in CallingService!!)
3. CallingService now ends or does other stuff.
4. WorkerService has defined a correlationSet in which is defined a property (and property alias) pointing to the ID in its input message for the initiate operation
5. the WorkerService instance starts up, receives the input data and immediately goes into a wait, pending receipt of a "stop" message correlated on the ID. Note that the stop message has the same input request message as the "initiate" operation.
6. The StopService is invoked. (NB: no correlationSet defined in StopService!!) This invokes the WorkerService "stop" operation, which is defined to use the same input request message as the "initiate" operation, so it also has the ID field. So the ID "id0001" is set up in the request message before the "stop" is invoked.
7. The WorkerService instance is now woken up as it has correlated on the ID field in the message. This ensures that the right instance is invoked. If there are several waiting for a "stop", only the instance waiting on the ID of "id0001" will be woken up.
8. WorkerService instance for ID "id0001" now finishes its work.

Don't forget that in this scenario ONLY the service which is waiting around (WorkerService) needs to do or know anything about correlationSets. The correlation ID passed by the CallerService and the StopService are just part of the regular data passed in on the input request. No need to define correlationSets on these two services.

One other thing. I got into a problem because both my operations were using the same input request message XML element, although different SOAP Actions. You should use different request message structures (best practice!). The properties for the correlation can point to different places in different messages - i.e. same property id but different XPath depending on the message!

This post is useful BPEL background on correlation:
http://www.ibm.com/developerworks/webservices/library/ws-bpelcol6/

See also Anthony Reynolds on the subject:
http://blogs.oracle.com/reynolds/2005/12/bpel_correlation.html

Tuesday, June 08, 2010

Oracle BPEL Worklist Application

Note to self on Oracle BPEL/BPM/BPA Human Interaction / Worklist task handling...

To add a Worklist interaction to a BPEL process, add a "Human Task" from the Component Palette. By default, this is set up with an Invoke to initiate the task, and also a Receive to receive the response.

The Receive causes the task to return immediately, which doesn't help if you want to try out the actual Human Interaction bit. If you comment out the Receive, and replace it with a Pick on the same partner link (to wait for an "onTaskCompleted" message (or it could be "onTaskAssigned", or "onTaskUpdated", or even "onSubTaskUpdated", depending what you want to do with it...)), you can cause it to wait for a real response. I'll come to generating that in a minute.

On the Pick, also add an Alarm branch to cause it to time out after, say, 30 minutes.
After the Pick, by default a set of options are generated to handle what comes back from the task once it has been dealt with. The default outcomes are APPROVE and REJECT, but the outcome can also become EXPIRED, STALE, and others.

Adding the Human Task also causes a .task to be opened, with a whole bunch of defaults filled in. For a test, you can set the task to be completed by a valid user "approving" or "rejecting" the task. To set the Human Task up to do this, open up the Assignment and Routing Policy section and click on the green plus to add a Participant. Fill in the dialogue to add a name with a userid of "bpeladmin". This allows you to use a default user who should be included in the default installation. You should now see that you have one user acting as a "SingleApprover". Save the Human Task.

If you now deploy and invoke the BPEL process, you should now see a process instance sitting there waiting for the Human Task to complete.

To complete the Human Task, you need to log onto the Worklist Application provided in the default install. Under Windows, if you're running the BPEL/BPM on your local machine, the default Worklist application is under Start -> All Programs -> -> Oracle BPEL Process Manager -> Worklist Application.
This resolves to the URL where the Worklist application is running. It'll be something like:
http://localhost:8888/integration/worklistapp/Login

If you login with the user that you used for the task - a usable default one seems to be "bpeladmin" with password of "welcome1". This should log you into the BPM Worklist Application and you should see the Task sitting there in the "My Tasks" section of the logged-in user.

You can now choose what to do with the task. If you "approve", or "reject", you should then see the BPEL process instance completing on the BPEL console.

Tuesday, June 01, 2010

How to stop an Oracle AQ queue

Run the following as an anonymous block of PL/SQL:

BEGIN
DBMS_AQADM.STOP_QUEUE(queue_name => 'my_queue_name', enqueue => false, dequeue => true);
END;

The above stops dequeuing from the queue (because dequeue=true).
The opposite command is START_QUEUE.

Useful post on working with AQ:
http://www.oracle-developer.net/display.php?id=411

And if you're looking for how to view the data that's on your queue, see this page:
http://rwijk.blogspot.com/2009/02/whats-in-my-jms-queue.html
Very useful post on how to look into the data, e.g.
SELECT QT.USER_DATA.TEXT_VC FROM <queue table name> QT;
(note use of QT table alias to refer to it...)

Monday, January 04, 2010

Oracle BPEL (10g): Email Activity

Noticed that, if you create an Email Activity, the Oracle BPEL Process Designer will default to using the multipart options. Which means that even if you just want some plain text, you'll end up with an email which has no text but 1 attachment (containing your text). You can untick the "multipart" option in the Email dialogue, but if you go back into the design view, it will be re-ticked. So, save your option without going back into the Design View!! Also, you may need to set the MIME option manually from "text/html" to "text/plain" (in the Source view) or Outlook won't display it right by default. What a fuss, eh?

Tuesday, September 15, 2009

Yes No Probably



Infuriating. They have deliberately left out one option (and the one I would probably tick): "Probably Not".

Sunday, September 13, 2009

Oh FFS

All I want to do is extract a few 100MB of zip file to my Desktop, and here's what Windows tells me:



Why can't they bloody well fix this sort of moronicness?
Cf. this cartoon.

Wednesday, August 26, 2009

Useful article on WSDL styles...

is here. Very good summary. An overview would be:

rpc-encoded: SOAP body has a child with the method name. Child elements of the method are type encoded e.g. with an xsi:type attribute. Not WS-I compliant.

rpc-literal: similar to rpc-encoded but the child elements don't have type attributes, which are probably overhead anyway, but means the message can't be validated.

document-encoded: is never used.

document-literal: no element inside the SOAP body which tells you which method to invoke. Maybe that's fine if you know what sort of content to expect, e.g. on a particular messaging channel, or URL.

document-literal-wrapped: variant of the above, but with a child element of the SOAP body to wrap the parameters to a method, which gives you an easy way to dispatch the method to a handler.

Thursday, July 09, 2009

Local WSDL

When wsimport creates artefacts for accessing a web service, it uses the URL which you specify. However maybe you don't want requests for that WSDL traversing the network when you access a service. In these cases you can store the WSDL locally and access it as a local resource.

To do this, do something like:
URL wsdlURL = this.getClass().getClassLoader().getResource("MyTestService.wsdl");
if (wsdlURL==null) {
LOG.error("unable to get WSDL from local file...");
} else {
LOG.debug("Getting WSDL from: " + wsdlURL.toExternalForm());
}

This should try to retrieve the WSDL from somewhere accessible by the application. In practice, you need to put the WSDL on the classpath, for example in the "WEB-INF/classes" folder.

I needed to do this because the JBoss I'm deploying to doesn't support OASIS Catalogs, so you can't point an application to local WSDL by means of the jax-ws-catalog.xml file that I posted about here.

Labels:

Friday, July 03, 2009

First time i've seen this...