Wednesday, May 27, 2009

JPA: Mapping Created and Updated Columns

To quickly follow up on my last post about CREATED and UPDATED columns for an entity named Map in MySQL, I thought I would add the equivalent JPA declarative ORM definition from my orm.xml:
  <entity class="Map" name="Map" access="FIELD">
<table name="MAP"/>
<attributes>
<id name="id">
<column name="ID" nullable="false"/>
<generated-value strategy="SEQUENCE"/>
</id>
<basic name="updated">
<column name="UPDATED" nullable="true"/>
<temporal>DATETIME</temporal>
</basic>
<basic name="updated">
<column name="UPDATED" nullable="true"/>
<temporal>TIMESTAMP</temporal>
</basic>
</entity>

Friday, May 8, 2009

MySQL: Adding Created and Updated Columns

I had a requirement to add a Last-Modified header to GET requests for an entity called Map in a service I was developing. I figured it would be a good idea to track that information in the MySQL database backing the service instead of in the application itself with a column named UPDATED. In other words, I wouldn't have to explicitly set andupdate the values during the lifetime of the Map.

While I was at it, I also thought it would be a good idea to add a CREATEDcolumn to track when the Map came into existence in case that information would be useful later.

At table creation time you can add the columns with the following SQL (which omits any other useful attributes or columns):

  CREATE TABLE MAP (
ID INT NOT NULL AUTO_INCREMENT,
CREATED DATETIME NOT NULL DEFAULT '1900-01-01 00:00:00',
UPDATED TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
);
The columns can also be added after the table has been created, assigning the defaults to each table row:
  ALTER TABLE MAP ADD CREATED DATETIME NOT NULL DEFAULT '1900-01-01 00:00:00';
ALTER TABLE MAP ADD UPDATED TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
Finally a trigger can be used, which can be added at anytime, to have the CREATED column be given a value on an INSERT:
  CREATE TRIGGER MAP_CREATED BEFORE INSERT ON MAP
FOR EACH ROW SET NEW.CREATED = NOW();
With the trigger, the default on the CREATED column wouldn't exactly be needed, and in fact the table could be created without it, leaving the NOT NULL clause intact.

The resulting table definition:

mysql> DESCRIBE MAP;
+---------+-----------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-----------+------+-----+---------------------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| CREATED | datetime | NO | | 1900-01-01 00:00:00 | |
| UPDATED | timestamp | NO | | CURRENT_TIMESTAMP | |
+---------+-----------+------+-----+---------------------+----------------+
3 rows in set (0.00 sec)

Thursday, April 30, 2009

Mule: Sending a JMS Message to WebSphere MQ

The Mule Client documentation example for sending a JMS message to a JMS queue seems simple enough:
    MuleClient client = new MuleClient();
client.dispatch("jms://my.queue", "Message Payload" null);
I was having trouble sending a JMS message to endpoint hooked to the following WebSphere MQ connector. The connector has a JMS to Object transformer for the incoming message. Sending a String as in the example produced an execption related to the connection factory stating that the incoming object was of type Class and not a JMS message. The connector:
  <jms:connector name="jmsConnectorWMQ"
connectionFactory-ref="WMQConnectionFactory"
maxRedelivery="5"
specification="1.1"
persistentDelivery="true"
numberOfConcurrentTransactedReceivers="5">
<service-overrides inboundTransformer="Jms2Obj"/>
</jms:connector>

<jms:jmsmessage-to-object-transformer name="Jms2Obj"/>
The connection factory:
  <spring:bean name="WMQConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<spring:property name="transportType" value="1"/>
<spring:property name="hostName" value="${jms.connection.hostname}"/>
<spring:property name="port" value="${jms.connection.port}"/>
<spring:property name="queueManager" value="${jms.queue.manager}"/>
<spring:property name="channel" value="${jms.connection.channel}"/>
</spring:bean>

I was able to create and send a JMS message with the following method. Without giving the ObjectToJMSMessage transformer an endpoint, an exception was thrown stating the transformer requires a javax.jms.Session. The String to send is transformed to a JMS message to make the connector happy.

The URL returned by the getUrl() method below was the address of a JMS queue, for example: jms://request.queue. Im using MuleClient.send() because I want the response returned synchronously.

The method:

protected String sendRequest(Object request) throws Exception {

EndpointFactory endpointFactory = new DefaultEndpointFactory();
MuleContext context = MuleServer.getMuleContext();
endpointFactory.setMuleContext(context);
ImmutableEndpoint endpoint = endpointFactory.getInboundEndpoint(getUrl());

ObjectToJMSMessage transformer = new ObjectToJMSMessage();
transformer.setEndpoint(endpoint);

Object transformedMessage = transformer.doTransform(request, "UTF-8");

MuleClient client = new MuleClient();
MuleMessage responseMessage = client.send(getUrl(), transformedMessage, null);
String response = responseMessage.getPayloadAsString(ENCODING);

return response;
}

This seems like a lot of work to me to send a simple JMS message to WebSphere MQ, but it works. A suggestions for alternative would be greatly appreciated.

A better approach: I left this as a comment but it doesn't display too nicely...

With com.ibm.mqjms.jar, sending the JMS message is much easier. I wish I would of found this earlier.

With the following imports:
    import com.ibm.jms.JMSTextMessage;
import com.ibm.mq.jms.MQJMSStringResources;
The original method is greatly simplified to:
    protected String sendRequest(Object request) throws Exception {

MQJMSStringResources resources = new MQJMSStringResources();
JMSTextMessage jmsMessage = new JMSTextMessage(resources, (String)request);
jmsMessage.setText((String)request);

MuleClient client = new MuleClient();
MuleMessage responseMessage = client.send(getUrl(), jmsMessage, null);

String response = responseMessage.getPayloadAsString(ENCODING);

return response;
}

Sunday, April 26, 2009

Using tidy to Format XML

Here's an exmaple of using tidy to format XML:
tidy -utf8 -xml -w 255 -i -c -q -asxml
I like to use an alias to work with files easily:
$ alias xmltidy="tidy -utf8 -xml -w 255 -i -c -q -asxml"

$ xmltidy some-file.xml > tidy-file.xml
You can also change a file in place:
$ xmltidy -m some-file.xml

Friday, April 3, 2009

Groovy: Pretty Printing XML

A script for pretty printing XML in Groovy:
#!/usr/share/groovy/bin/groovy
import org.xml.sax.SAXParseException

def xml = new File(args[0]).text
def stringWriter = new StringWriter()
def printWriter = new PrintWriter(stringWriter)

try {
def node = new XmlParser().parseText(xml)
new XmlNodePrinter(printWriter).print(node)
println stringWriter.toString()
} catch(SAXParseException spe) {
println spe.getMessage()
}
Suggestions for alternatives would be appreciated!

Mule: Displaying HTTP Outbound Responses

I had been tasked with adding an endpoint to my Mule service for verifying other service endpoints. One of the requirements was that the endpoint be HTTP so that a browser could be used to retrieve the verification report.

Originally, when hitting the endpoint in my browser, the resulting HTML was displayed as plain text.

I resolved this by adding the HtmlResponseTransformer below:
    <http:endpoint name="VerificationEndpoint"
host="localhost"
port="28080"
path="services/verify"
method="GET"
synchronous="true"
responseTransformer-refs="HtmlResponseTransformer"/>

<message-properties-transformer name="HtmlResponseTransformer">
<add-message-property key="Content-Type" value="text/html"/>
</message-properties-transformer>

<model name="setup">
...
<service name="verify">
<inbound>
<http:inbound-endpoint ref="VerificationEndpoint"/>
</inbound>
<component>
<spring-object bean="endpointVerifier"/>
</component>
</service>
...
</model>
It is worth noting the HTTP Transport Documentation states that HTTP endpoints are synchronous by default, but it did appear to be the case in my experience.

Wednesday, February 18, 2009

Maven Assemblies: Including Runtime Dependencies

I wanted to share a tip I picked up from Maven: The Definitive Guide
Previously, I thought you had to list every runtime dependency you wanted to include in a dependencySet:
   <dependencySets>
<dependencySet>
<includes>
<include>commons-dbcp:commons-dbcp</include>
…
</includes>
<outputDirectory>mule/lib/user</outputDirectory>
</dependencySet>
</dependencySets>
But all runtime dependencies can be brought into the assembly with an empty dependencySet element (runtime scope implicitly includes compile scope):
   <dependencySet/>
This will put all the runtime dependencies in the root of the assembled artifact, so you can add an outputDirectory:
   <dependencySet>
<outputDirectory>mule/lib/user</outputDirectory>
</dependencySet>
And in the case where you want to exclude something (such as mule-#.tar.gz or isoft-#.tar.gz) you can add exclusions:
   <dependencySet>
<outputDirectory>mule/lib/user</outputDirectory>
<excludes>
<exclude>*:tar.gz</exclude>
</excludes>
</dependencySet>
Doing things this way puts a heavier burden on properly managing your dependencies however (which really is a good thing). If transitive dependencies you may not need are not excluded in the POM’s dependency declaration or the parent’s dependencyManagement, the transitive dependencies will end up in your artifact, leading to potential collisions and jar bloat. An example of an exclusion:
    <dependency>
<groupId>toplink.essentials</groupId>
<artifactId>toplink-essentials</artifactId>
<scope>runtime</scope>
<excludes>
<exclude>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
</exclude>
</excludes>
</dependency>
You can run each of the following to help with your dependency manangement:
mvn dependency:analyze
mvn dependency:resolve
mvn dependency:tree