Last week I was struggling to get an MQ adapter configured using a WebLogic deployment plan. I must have been especially low on brain power that day, as they're really not all that complex. Still, they
are tricky if you've never seen them before (as I hadn't), so here are some pointers to help you out.
These deployment plans turn out to be part of an implementation of
JSR-88. Don't try to read that spec unless you feel significantly more masochistic than I do though. Suffice it to say that - under WebLogic, at least - you can use them to provide server-specific configuration information to an application.
You may want to use a plan if your config is included in an jar/war/ear/etc. file; for instance in an included web.xml. Having config in such a place can be a pain, as you typically don't want to change those *ar files after QA has signed off on them. A deployment plan lets you work around this problem by telling the server to pretend that the config was actually at bit (or entirely) different from what those files in the *ar said.
The way this actually works is somewhat unintuitive, but it does work. Under WebLogic, you use an XML document that conforms to
this schema. (I can't comment on other platforms, as I have only tried this on WebLogic.)
The most interesting part of this schema is the module-override element. With this element, we can specify what descriptors to update, and in what modules (rar, jar, etc.). For instance:
<module-override>
<module-name>MQSeriesAdapter.rar</module-name>
<module-type>rar</module-type>
<module-descriptor external="false">
<root-element>weblogic-connector</root-element>
<uri>META-INF/weblogic-ra.xml</uri>
<variable-assignment>
...
</variable-assignment>
</module-descriptor>
</module-override>
This config will update the META-INF/weblogic-ra.xml descriptor in MQSeriesAdapter.rar. The actual fields being updated are specified in the variable-assignment block. (You can have multiple of those, by the way.)
Those variable-assigment blocks are where things get confusing. Before I explain, allow me to show you their basic form.
<variable-assignment>
<name>name</name>
<xpath>pseudoXPath</xpath>
<operation>add</operation> <-- Can also be remove or replace. -->
</variable-assignment>
The idea is that the data from the "name" element gets assigned to the location in the descriptor (i.e. META-INF/weblogic-ra in the example) indicated with the "xpath" element. The "operation" element specifies if this value must be added, removed or replaced. (The default is "add", and in this case, any XML elements that are specified in the xpath tag, but missing in the target document, will be added.)
This is where things start getting confusing. First of all, you can't actually specify the value you want to assign in the "name" element. There is an element of indirection here in that you must assign this value to a variable first, and then you can refer to this variable here. Sound confusing? I sure thought it was.
Here's an example of how it works:
<variable-definition>
<variable>
<name>myVar</name>
<value>niftyValue</value>
</variable>
</variable-definition>
<module-override>
<module-name>MQSeriesAdapter.rar</module-name>
<module-type>rar</module-type>
<module-descriptor external="false">
<root-element>weblogic-connector</root-element>
<uri>META-INF/weblogic-ra.xml</uri>
<variable-assignment>
<name>myVar</name>
<xpath>pseudoXPath</xpath>
</variable-assignment>
</module-descriptor>
</module-override>
In the example we assign the value "niftyValue" via the variable myVar. Ridiculously circumlocutious (word of the day), but it works.
There's something even more confusing though. Have you noticed how I put the value "pseudoXPath" in every "xpath" element so far? This is because despite what the name suggests, this element doesn't actually accept proper XPath!
JSR-88 restricts the XPaths allowed to just those who contain only ".", "..", "/", and tag names. I suppose it makes sense to restrict the allowed expressions a bit, considering that the expression can be used to create a new element. (In which case the plan processor must manipulate the XML until the XPath expression evaluates to a node. Could be tricky for complex XPaths.) Still, as it's now, it's probably a bit too restrictive.
Fortunately, WebLogic seems to accept an enhanced syntax, but this makes it deviate even more from the XPath standard. I haven't yet found proper documentation of the syntax, but I know that it accepts
XPath predicates with equality comparisons. Unlike proper XPath though, they must be preceded by a slash ("/"). So you can have a construction like
book/[title="Lord of the Rings"]
to select only books with a title element with value "Lord of the Rings".
Don't bother with namespaces in these XPaths, by the way. WebLogic seems to ignore namespaces when processing them, which I guess is usually pretty convenient. Yet another way in which it differs from true XPath, however.
Putting it all together, you could end up with something like this:
<variable-definition>
<variable>
<name>port</name>
<value>1414</value>
</variable>
</variable-definition>
<module-override>
<module-name>MQSeriesAdapter.rar</module-name>
<module-type>rar</module-type>
<module-descriptor external="false">
<root-element>weblogic-connector</root-element>
<uri>META-INF/weblogic-ra.xml</uri>
<variable-assignment>
<name>port</name>
<xpath>/weblogic-connector/outbound-resource-adapter/connection-definition-group/[connection-factory-interface="javax.resource.cci.ConnectionFactory"]/connection-instance/[jndi-name="eisMQ/MQAdapter"]/connection-properties/properties/property/[name="portNumber"]/value</xpath>
</variable-assignment>
</module-descriptor>
</module-override>
By now you should have a pretty good idea of how these plans work. If you want to know how to deploy them, then you could do worse than to check out
this helpful blog.