Friday, April 3, 2009

Switch JBossESB-4.5.GA from HSQL to MSSQL

To switch JBossESB from the default HSQL embedded database to a "real" database like MSSQL, the persistence configuration of JMS, jUDDI, ESB MessageStore and jBPM needs updating.

1. JMS
rm server/default/deploy/jms/hsqldb-jdbc2-service.xml
cp docs/examples/jms/mssql-jdbc2-service.xml server/default/deploy/jms
cp docs/examples/jca/mssql-ds.xml server/default/deploy/jms
mv server/default/deploy/jms/hsql-jdbc-state-service.xml server/default/deploy/jms/mssql-jdbc-state-service.xml


update the mssql-jdbc-state-service.xml to point to the MSSQLDS datasource

<depends optional-attribute-name="ConnectionManager">jboss.jca:service=DataSourceBinding,name=MSSQLDS</depends>

update the "Security domain for JBossMQ" in the server/default/conf/login-config.xml to java:/MSSQLDS

2. jUDDI
cp docs/examples/jca/mssql-ds.xml server/default/deploy/jbossesb.sar/juddi-ds.xml
update the juddi-ds.xml, make sure the <jndi-name>juddiDB</jndi-name>
update the server/default/deploy/jbossesb.sar/esb.juddi.xml to make sure the mssql sql is used to create the jUDDI tables

<entry key="juddi.sqlFiles">juddi-sql/mssql/create_database.sql,juddi-sql/mssql/import.sql</entry>

3. JBossESB MessageStore
rm server/default/deploy/jbossesb.esb/hsql-ds.xml
cp docs/examples/jca/mssql-ds.xml server/default/deploy/jbossesb.esb

update the mssql-ds.xml, make sure the <jndi-name>JBossESBDS</jndi-name>
update the server/default/deploy/jbossesb.esb/jbossesb-service.xml to point to the mssql sql for creating the message table

<attribute name="SqlFiles">
message-store-sql/mssql/create_database.sql
</attribute>

4. jBPM
rm server/default/deploy/jbpm.esb/hsql-ds.xml
cp docs/examples/jca/mssql-ds.xml server/default/deploy/jbpm.esb/

update the mssql-ds.xml, make sure the <jndi-name>JbpmDS</jndi-name>
update the server/default/deploy/jbpm.esb/hibernate.cfg.xml to make sure the SQLServerDialect is used

<!-- hibernate dialect -->
<property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>

update the server/default/deploy/jbpm.esb/jbpm-service.xml so it points to the mssql sql file

<attribute name="SqlFiles">
jbpm-sql/jbpm.jpdl.mssql.sql,
jbpm-sql/import.sql
</attribute>

Not that the import.sql tries to set the primary key, which is an autoincrement column. MSSQL does not like this. Simply setting this column from this script will get you going.
5. Finishing up
To Finish up, make sure you add the mssql database driver jar to the server/default/lib directory, and make sure you added your credentials to the various mssql-ds.xml files.

<datasources>
<local-tx-datasource>
<jndi-name>JbpmDS</jndi-name>
<connection-url>jdbc:jtds:sqlserver://192.168.1.2:1433/jbossesb</connection-url>
<driver-class>net.sourceforge.jtds.jdbc.Driver</driver-class>
<user-name>jbossesb_admin</user-name>
<password>admin</password>
<!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
<metadata>
<type-mapping>MS SQLSERVER2000</type-mapping>
</metadata>
</local-tx-datasource>

Make sure this user has table create rights, so that when you start up JBossESB it can create the tables.

MSSQL Drop all constraints from the database

Recently I had to drop all tables from a MSSQL Server Database, and this proved to be harder than expected because of foreign key contraints in the database. I found a post on how do disable them but that turned out to be not enough to allow to drop the tables. Instead I had to drop all the constraints from the database. The few lines below generate the commands to do this.

select
'ALTER TABLE ' + so.table_name + ' DROP CONSTRAINT ' + so.constraint_name
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS so

Wednesday, March 25, 2009

Smooks XML2Java Transformation

Previously I wrote about using Smooks for XML2XML transformations. Today I worked on an XML2Java transformation. It so happens that my incoming XML is completely flat, and looks like

<my-example-data>
<id>1234</id>
<fname>First Name</fname>
<mname>Middle Name</mname>
<lname>Last Name</lname>
<jobTitle>Job Title</jobTitle>
</my-example-data>

Which lends itself really well to be stuffed into a Map, with the key being the name of the element. This is where a really handy Smooks trick comes in handy

<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.1.xsd">
<jb:bindings beanId="inquiryMap" class="java.util.HashMap" createOnElement="$document">
<jb:value data="inquiry-email-data/*"/>
</jb:bindings>
</smooks-resource-list>

Now when running the following code:

Smooks smooks = new Smooks("smooks-config.xml");
JavaResult javaResult = new JavaResult();
smooks.filter(new StreamSource(new StringReader(xml)), javaResult);
Map results = (Map<String,String>) javaResult.getBean("inquiryMap");
System.out.println("result=" + results);

It prints out:

results={lname=Last Name, mname=Middle Name, fname=First Name, id=1234, jobTitle=Job Title}

The Smooks User Guide talks about something similar when your XML uses property elements.

By the way if you like mapping out your transformation graphically you should check out the new Smooks Graphical Editor.

The Eclipse plugin can be downloaded from http://www.smooks.org/news/eclipseeditorforsmooksinjbosstools.

Thursday, March 12, 2009

JBoss Deployment Dependencies of a War

When your war file depends on another service to deploy first you can add a depends element in the WEF-INF/jboss-web.xml. This will guaranty the deployment order, and the war file will not be deployed until the PluginManager Service is deployed first.
 

jboss.admin:service=PluginManager

I know I looked for this before and was not able to find it. Now I won't forget.

--Kurt

Tuesday, February 17, 2009

Using Regexp in Drools 5

I've spend waaay too much time on this, so I need to scribble this 'note to self'. I'm working with JBossESB and I have a piece of text in the body of the message. Now if a certain word is found in this text I want to route the message a certain way. This example is based on the simple_cbr quickstart.

1. So let's first take a look how to match a word in a string. To demonstrate how to do this I created this logging rule:

rule "Logging"
when
b: String(this matches "(?i).*Order(.|\n|\r)*" && this matches ".*EST(.|\n|\r)*")
then
System.out.println("b=|" + b + "|");
end

This rule will print out the incoming string if both the words 'Order' and 'EST' are matched.
The (?i) means 'ignore case', .*Order*. means the word 'Order' or 'order' anywhere in the string will be matched, but this will still not work if the string is multi-line (The '.' character does not match the newline character). So to fix that we need to make it .*Order(.|\n)*. Same story for the '\r'. This is the first word match which we can combine with '&&' or '||' with other matches like I did here looking for 'EST'.

2. Finally to push the String from the default place in the ESB message into the rules engine you need to use an object path of "body.'org.jboss.soa.esb.message.defaultEntry'" as shown in the XML fragment taking from a jboss-esb.xml.


<action class="org.jboss.soa.esb.actions.ContentBasedRouter" name="ContentBasedRouter">
<property name="ruleSet" value="ShippingRules.drl"/>
<property name="ruleReload" value="true"/>
<property name="object-paths">
<object-path esb="body.'org.jboss.soa.esb.message.defaultEntry'" />
</property>
<property name="destinations">
<route-to destination-name="express" service-category="ExpressShipping" service-name="ExpressShippingService"/>
<route-to destination-name="normal" service-category="NormalShipping" service-name="NormalShippingService"/>
</property>
</action>

alternatively you can use a path of esb="BODY_CONTENT".

jUDDI-3.0.0.alpha released

For details see the jUDDI website or the TSS announcement. This release duplicates the functionality that is available in jUDDIv2.x and we'll be working on the newly added UDDI v3 APIs (such as the Subscription, Replication and Custody transfer) going forward. To get started we created a ready-to-go UDDI v3 server in one download: juddi-tomcat.zip (based on jUDDI-3.0.0.alpha, Tomcat and Derby). Please contact us if you want to help out. Now that the jUDDI-v3.x code base is functional it is relativity easy to contribute.

--Kurt

Friday, February 13, 2009

Java Architecture Management

Yesterday I attended a NEJUG meeting presented by Alexander von Zitzewitz called "Java Architecture Management or how to avoid the structural erosion of your code base". It was a pretty entertaining talk where he reviewed a number of scenarios that lead to the creation of unmaintainable complexity. He confirmed a lot of what I already knew, but nicely formulated and explained. He argued that no documentation is going to help you, it's prohibitively expensive to create and always outdated by the latest code. A general theme was that you need to have an architecture that slices horizontally (architectural layers) as well as vertically (functional slices). Think of vertical slices as your java package naming and how packages end up in a jar. This way you end up with a grid of subsystems. Next you can start analyzing the dependencies between the subsystems. He described a number of code metrics that can be used to quantify the number of architecture violations in the code. He came up with a list of 6 rules that one should follow to write maintainable code:

Rule 1: Define a cycle free logical architecture down to the level of subsystems and a strict and consistent package naming convention
Rule 2: Do not allow cyclic dependencies between different packages
Rule 3: Keep the relative ACD low (< 7% for 500 compilation units, NCCD < 6)
Rule 4: Limit the size of Java files (700 LOC is a reasonable value)
Rule 5: Limit the cyclomatic complexity of methods (e.g. 15)
Rule 6: Limit the size of a Java package (e.g. less than 50 types)

To break a dependency cycle you can should introduce an interface; this reverses the dependency. It is that simple. This leads to the observation that "good code" can be recognized using certain metrics (see also a white paper by Robert Martin. Good code should have a certain ration of abstractness (classes vs interfaces), and if more code depends on your code, you will likely need more interfaces. The two extremes of this "metric distance" from the optimal ratio, are:
zone of uselessness which means a high number of interfaces and few things depending on you. This happens when coders plan for complexity that never happened.
zone of pain which means very few interfaces and lots of code depends on you. So each change in your class can break lots of other things elsewhere. This usually happens when people cut corners to make a deadline.

To monitor this adherence to the rules you need a tool. Commercially he listed three; Lattix here in Massachusetts, Structure101 and SonarJ, which is his product and which was later demoed. I was actually involved in a case study with Lattix a few years ago, which was interesting but felt like moving the chair on the deck of the Titanic. The case study only took into account the Java side and our major issue was the duplication of code on the server (Java) and the client side (Javascript). Code duplication is something that is not easily picked up and certainly not when it appears in the different Languages. We were simply to deep into our own poo to fix things. I think a rewrite was the only option for that product. Anyway I still learned a lot from it. For one that it is never too early to hook up a static code analyzer to the nightly build. If you register with hello2morrow you can download a free version of SonarJ meant for projects with fewer then 500 Java classes. If you want to go Open Source then you can try: PMD, jDepend (dependencies only) and Architecture Rules (on top of jDepend).

The meeting really confirmed my own experiences, that the process of creating good code is simple. You just have to follow it *all the f***ing time* (much like Bryan Liles' TATFT framework). Bad code is like a black hole attracting other bad code. So simply don't put black holes in your code! If your system gets large, make sure you use tools to monitor that none of these simple rules are broken. Hook them up to the nightly build and have any violations be fixed the very next day. Note that you need an architecture before you can use any of these tools!

--Kurt