<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mersoft Corporation Blog</title>
	<atom:link href="http://blog.mersoft.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mersoft.com</link>
	<description>Achieve, Compete, and Evolve</description>
	<lastBuildDate>Wed, 21 Mar 2012 20:23:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Getting started with Mobicents Diameter</title>
		<link>http://blog.mersoft.com/2012/03/21/getting-started-with-mobicents-diameter/</link>
		<comments>http://blog.mersoft.com/2012/03/21/getting-started-with-mobicents-diameter/#comments</comments>
		<pubDate>Wed, 21 Mar 2012 20:23:58 +0000</pubDate>
		<dc:creator>Mandi Zinn</dc:creator>
				<category><![CDATA[Java/Java Frameworks]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[AVP]]></category>
		<category><![CDATA[Diameter]]></category>
		<category><![CDATA[Mobicents Diameter]]></category>

		<guid isPermaLink="false">http://blog.mersoft.com/?p=411</guid>
		<description><![CDATA[For a project at Mersoft, I was tasked with learning how to make a call to a 3GPP IMS system using diameter. Since diameter was a new concept for me, the first thing I did was to figure out what diameter was. For that I turned to this article on Wikipedia.
Now that I knew what [...]]]></description>
			<content:encoded><![CDATA[<p>For a project at <a href="http://www.mersoft.com">Mersoft</a>, I was tasked with learning how to make a call to a 3GPP IMS system using diameter. Since diameter was a new concept for me, the first thing I did was to figure out what diameter was. For that I turned to <a href="http://en.wikipedia.org/wiki/Diameter_(protocol)">this</a> article on Wikipedia.</p>
<p>Now that I knew what it was and the structure of the calls, the next task was to set up an environment. I was pointed in the direction of using Mobicents Diameter with Open IMS. This <a href="http://blog.mersoft.com/2012/03/16/installing-and-configuring-open-ims-and-mobicents-diameter/">blog</a> covers what I did to set up the environment.</p>
<p>Now that I had my environment set up, I was able to learn diameter and document the steps to go through to create a new diameter call.</p>
<p>Here&#8217;s the process:</p>
<p><b>1.  Figure out which 3GPP Technical Specification (TS) documents the interface of the diameter call the application is going to perform.</b></p>
<p>Mobicents diameter supports a limited amount of diameter calls. You can see if the interface you&#8217;re wanting to use is supported by going to <a href="http://www.mobicents.org/diameter/index.html">http://www.mobicents.org/diameter/index.html</a>. If you&#8217;re unsure of which interface you&#8217;ll be using, Wikipedia has a list of the interfaces and their descriptions <a href="http://en.wikipedia.org/wiki/IP_Multimedia_Subsystem">here</a>. The mobicents site also lists which 3GPP TS corresponds to each IMS interface. These can be downloaded from <a href="ftp://ftp.3gpp.org/specs/">ftp://ftp.3gpp.org/specs/</a> (click on the 3GPP release you&#8217;re wanting to use, then the series number (in the example below, it&#8217;s 29), then the document number.  For this tutorial, I&#8217;m going to perform a Location Info Request. The request is documented in <a href="ftp://ftp.3gpp.org/specs/2012-03/Rel-11/29_series/29229-b00.zip">TS 29.229</a>. Here&#8217;s what the request looks like:</p>
<pre>&lt;Location-Info-Request&gt; ::=    &lt; Diameter Header: 302, REQ, PXY, 16777216 &gt;
                               &lt; Session-Id &gt;
                               { Vendor-Specific-Application-Id }
                               { Auth-Session-State }
                               { Origin-Host }
                               { Origin-Realm }
                               [ Destination-Host ]
                               { Destination-Realm }
                               [ Originating-Request ]
                               *[ Supported-Features ]
                               { Public-Identity }
                               [ User-Authorization-Type ]
                               [ Session-Priority ]
                               *[ AVP ]
                               *[ Proxy-Info ]
                               *[ Route-Record ]</pre>
<p><b>2. Configure JBoss to route calls for the particular application id and vendor id of the call you&#8217;re wanting to make.</b><br />
To do this, you have to edit the configuration of the mobicents-diameter-mux library. If you recall from the <a href="http://blog.mersoft.com/2012/03/16/installing-and-configuring-open-ims-and-mobicents-diameter/">OpenIMS set up blog</a>, the file to edit is mobicents-diameter-mux-{version}/sar-jboss-5/src/main/resources/config/jdiameter-config.xml. You need to have a Realm with a vendor id of 10415 (for 3GPP) and an auth application id that matches the id in the TS</p>
<ul>
<li>For the Location-Info-Request, the TS (29.229) contains the following:
<pre>Message Format
&lt;Location-Info-Request&gt; ::=		&lt; Diameter Header: 302, REQ, PXY, 16777216 &gt;  ....</pre>
<p>The auth application id for this request is 16777216.</li>
</ul>
<p>Once the jdiameter-config.xml is edited, the mobicents-diameter-mux library must be re-built and re-installed into JBoss. </p>
<p><b>3. Set up the application for deployment into JBoss</b><br />
Since the mobicents diameter application must be deployed into a JBoss container, the application must be defined as either a sip servlet or an http servlet. For this example, I chose to use an http servlet to keep it as simple as possible and to show that you don&#8217;t have to use the sip servlet for making these calls.</p>
<ul>
<li>ContainerServlet.java
<pre>package com.mersoft.diameter.demo;

import javax.servlet.http.HttpServlet;

public class ContainerServlet extends HttpServlet {

	/**
	 *
	 */
	private static final long serialVersionUID = 5335116599234043697L;
}</pre>
</li>
</ul>
<p><b>4. Initialize the diameter components</b><br />
To initialize the diameter components, I used the same code the Mobicents Diameter examples use and adjusted it for the call I am trying to make.</p>
<ul>
<li>LocationInfo.java
<pre>package com.mersoft.diameter.demo;

import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;

import org.jdiameter.api.Answer;
import org.jdiameter.api.ApplicationId;
import org.jdiameter.api.Request;
import org.mobicents.diameter.api.DiameterMessageFactory;
import org.mobicents.diameter.api.DiameterProvider;
import org.mobicents.diameter.stack.DiameterListener;
import org.mobicents.diameter.stack.DiameterStackMultiplexer;

public class LocationInfo implements DiameterListener {

	/**
	 *
	 */
	private static final long serialVersionUID = -931426000146154787L;

	private static final long CX_DX_APP_ID = 16777216;
	private static final long GPP_VENDOR_ID = 10415;

	private DiameterStackMultiplexer muxMBean = null;
	private DiameterMessageFactory msgFactory = null;
	private DiameterProvider provider = null;

	public LocationInfo() throws Exception {

	    MBeanServer server = (MBeanServer) MBeanServerFactory.findMBeanServer(null).get(0);

	    Object object = server.invoke( new ObjectName("diameter.mobicents:service=DiameterStackMultiplexer"),
	    		"getMultiplexerMBean", new Object[]{}, new String[]{} );

	    if (object instanceof DiameterStackMultiplexer) {
	    	muxMBean = (DiameterStackMultiplexer) object;
	    } else {
	    	throw new Exception("Unable to retrieve the Diameter Stack Multiplexer");
	    }

	    // Create the Application-Id for Cx/Dx
	    ApplicationId[] appIds = new ApplicationId[]{ApplicationId.createByAuthAppId( GPP_VENDOR_ID, CX_DX_APP_ID )};
	    muxMBean.registerListener( this, appIds );

	    msgFactory =  muxMBean.getMessageFactory();
	    provider = muxMBean.getProvider();
	}

	public Answer processRequest(Request request) {
		// TODO Auto-generated method stub
		return null;
	}

	public void receivedSuccessMessage(Request request, Answer answer) {
	    System.out.println( "Received success message (Result-Code[" + answer.getResultCode() + "]) for Diameter Request with Session-Id [" + request.getSessionId() + "]" );
	}

	public void timeoutExpired(Request request) {
		System.out.println( "Timeout expired for Diameter Request with Session-Id [" + request.getSessionId() + "]" );
	}

}</pre>
</li>
</ul>
<p><b>5. Set up the call</b><br />
Based on the diameter header, we need to set up the following information:</p>
<ul>
<li>
<pre>&lt;Location-Info-Request&gt; ::=		&lt; Diameter Header: 302, REQ, PXY, 16777216 &gt;  ....</pre>
</li>
<li>LocationInfo.java
<pre>       public String retrieveLocationInfo(String user) {
		String locationInfo = null;

		try {
                        //LOCATION_INFO_REQUEST = 302
                        //CX_DX_APP_ID = 16777216
			Request req = (Request) this.msgFactory.createRequest( DiameterCodes.LOCATION_INFO_REQUEST, CX_DX_APP_ID);

			//TS says this is a proxiable request
			req.setProxiable(true);
                } catch (Exception e) {
			e.printStackTrace();
		}

		return locationInfo;

	}</pre>
</li>
</ul>
<p>The most difficult part of making the call, in my opinion, is adding the AVP&#8217;s. The AVP&#8217;s are defined in a variety of documents. What I found that worked best is starting with those that are defined in the 3GPP TS document. The next document I turned to was the one by IANA at <a href="http://www.iana.org/assignments/aaa-parameters/aaa-parameters.xml#aaa-parameters-14">http://www.iana.org/assignments/aaa-parameters/aaa-parameters.xml#aaa-parameters-14</a>. IANA refers to the RFC documents for those IMS AVPs it does not define (Once the RFC is known, Google can find the document <img src='http://blog.mersoft.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ).</p>
<ul>
<li>LocationInfo.java
<pre>		    //Add AVPs
		    AvpSet avps = req.getAvps();

		    //   &lt; Session-Id&gt;
		    //RFC 3588: &lt;DiameterIdentity&gt;;&lt;high 32 bits&gt;;&lt;low 32 bits&gt;[;&lt;optional value&gt;]
		    avps.addAvp( Avp.SESSION_ID, ("locationInfoSample;" + System.currentTimeMillis()).getBytes()  );

		    //   { Vendor-Specific-Application-Id }
	            //RFC 3588: &lt;Vendor-Specific-Application-Id&gt; ::= &lt; AVP Header: 260 &gt;
                    //    1* [ Vendor-Id ]
                    //   0*1{ Auth-Application-Id }
                    //   0*1{ Acct-Application-Id }
		    AvpSet vsaiAvp = avps.addGroupedAvp( Avp.VENDOR_SPECIFIC_APPLICATION_ID, true, false );
		    vsaiAvp.addAvp( Avp.VENDOR_ID, GPP_VENDOR_ID, true, false, true );
		    vsaiAvp.addAvp( Avp.AUTH_APPLICATION_ID, CX_DX_APP_ID, true, false, true );

		     //   { Auth-Session-State }
		    //IANA: 0 == State Maintained, 1 == No State Maintained
		    avps.addAvp( Avp.AUTH_SESSION_STATE, 0, true, false );

		    //   { Origin-Host }
		    avps.addAvp( Avp.ORIGIN_HOST, ("aaa://" + this.originIP + ":" + this.originPort).getBytes(), true, false );

		    //   { Origin-Realm }
		    avps.addAvp( Avp.ORIGIN_REALM, this.originRealm.getBytes(), true, false );

		    //   [ Destination-Host ]
		    avps.addAvp( Avp.DESTINATION_HOST, ("aaa://" + this.destinationIP + ":" + this.destinationPort).getBytes(), true, false );

		    //   { Destination-Realm }
		    avps.addAvp( Avp.DESTINATION_REALM, this.destinationRealm.getBytes(), true, false );

		    //   [ Originating-Request ]
		    //TS 29.229: 0 == ORIGINATING
		    //Since this is a 3GPP TS AVP, the vendor id must be included
		    avps.addAvp(Avp.ORIGINATING_REQUEST, 0, GPP_VENDOR_ID, true, false);

			//   *[ Supported-Features ]
		    // This is an optional AVP. We will not use it in this example

			//   { Public-Identity }
		    avps.addAvp(Avp.PUBLIC_IDENTITY, ("sip:" + user.replaceFirst( "sip:", "" )).getBytes(), GPP_VENDOR_ID, true, false );

			//   [ User-Authorization-Type ]
		    // TS 29.229: 0 == REGISTRATION, 1 == DE_REGISTRATION, 2 == REGISTRATION_AND_CAPABILITIES
		    avps.addAvp(Avp.USER_AUTORIZATION_TYPE, 2, GPP_VENDOR_ID, true, false);

			//   [ Session-Priority ]
			//   *[ AVP ]
			//   *[ Proxy-Info ]
			//   *[ Route-Record ]</pre>
</li>
</ul>
<p><b>6. Make the call and parse the results.</b></p>
<ul>
<li>According to TS 29.229, this is the Location Info Answer:
<pre> &lt; Location-Info-Answer&gt; ::=    &lt; Diameter Header: 302, PXY, 16777216 &gt;
                                &lt; Session-Id &gt;
                                { Vendor-Specific-Application-Id }
                                [ Result-Code ]
                                [ Experimental-Result ]
                                { Auth-Session-State }
                                { Origin-Host }
                                { Origin-Realm }
                                *[ Supported-Features ]
                                [ Server-Name ]
                                [ Server-Capabilities ]
                                [ Wildcarded-Public-Identity ]
                                *[ AVP ]
                                *[ Failed-AVP ]
                                *[ Proxy-Info ]
                                *[ Route-Record ]</pre>
</li>
</ul>
<p>The value I&#8217;m wanting is the Server-Name, which the TS says has an AVP code of 602. Here&#8217;s the rest of the code to make the call:</p>
<ul>
<li>LocationInfo.java
<pre>                Answer ans = (Answer) this.provider.sendMessageSync(req);

	        if (ans.getResultCode() != null) {
	                System.out.println("Received " + ans.getResultCode().getUnsigned32() + " " + ans.getResultCode().getUTF8String());

	  	        locationInfo = ans.getAvps().getAvp(Avp.SERVER_NAME).getUTF8String();
	        } else {
	        	System.out.println(ans.getAvps().getAvp(Avp.EXPERIMENTAL_RESULT).getUTF8String());
	        }</pre>
</li>
</ul>
<p>The only thing left is to update the servlet to perform the call:</p>
<ul>
<li>ContainerServlet.java
<pre>	private LocationInfo locationInfo;

	@Override
	public void init(ServletConfig servletConfig) throws ServletException {
		try {
			locationInfo = new LocationInfo();
		} catch (Exception e) {
			throw new ServletException(e);
		}
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String user = req.getParameter("user");
		PrintWriter out = resp.getWriter();
		if (user != null) {
			String result = locationInfo.retrieveLocationInfo(user);

			if (result != null) {
				out.println(result);
			} else {
				out.println("No result for " + user);
			}
		} else {
			out.println("No user");
		}

	}</pre>
</li>
</ul>
<p><a href="http://blog.mersoft.com/wp-content/uploads/2012/03/DiameterWithoutSip.zip">Here&#8217;s the entire example</a>.  Mobicents has a really good diameter/sip example <a href="http://code.google.com/p/mobicents/source/browse/trunk/servers/sip-servlets/sip-servlets-examples/diameter-openims">here</a>. This example makes a Subscription-Notification-Request to register for subscription updates, and shows how to use Diameter with sip.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.mersoft.com%2F2012%2F03%2F21%2Fgetting-started-with-mobicents-diameter%2F&amp;linkname=Getting%20started%20with%20Mobicents%20Diameter"><img src="http://blog.mersoft.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://blog.mersoft.com/2012/03/21/getting-started-with-mobicents-diameter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing and Configuring Open IMS and Mobicents Diameter</title>
		<link>http://blog.mersoft.com/2012/03/16/installing-and-configuring-open-ims-and-mobicents-diameter/</link>
		<comments>http://blog.mersoft.com/2012/03/16/installing-and-configuring-open-ims-and-mobicents-diameter/#comments</comments>
		<pubDate>Fri, 16 Mar 2012 22:45:39 +0000</pubDate>
		<dc:creator>Mandi Zinn</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Mobicents Diameter]]></category>
		<category><![CDATA[open IMS]]></category>

		<guid isPermaLink="false">http://blog.mersoft.com/?p=404</guid>
		<description><![CDATA[For a project at Mersoft, I was tasked with setting up an Open IMS environment to use with Mobicents Diameter. I used the article from here to get started.
I had to deviate from the Mobicents tutorial for these reasons:

I was using Open IMS from one server and Mobicents Diameter from another server
The tutorial used paths [...]]]></description>
			<content:encoded><![CDATA[<p>For a project at <a href="http://www.mersoft.com">Mersoft</a>, I was tasked with setting up an Open IMS environment to use with Mobicents Diameter. I used the article from <a href="http://www.mobicents.org/mss-diameter_sh.html">here</a> to get started.</p>
<p>I had to deviate from the Mobicents tutorial for these reasons:</p>
<ul>
<li>I was using Open IMS from one server and Mobicents Diameter from another server</li>
<li>The tutorial used paths no longer valid for the JBoss configuration and referenced a different version of mobicents-diameter-mux than the JBoss instance I was using used.</li>
<li>OpenIC is apparently no longer available. I used X-Lite4 instead.</li>
</ul>
<p>The first thing the article recommended was setting up Open IMS. I followed the link to the <a href="http://www.openimscore.org/installation_guide">Open IMS installation guide</a> and started following the guide.<br />
I was given access to a Ubuntu server for Open IMS. Here&#8217;s the libraries I had to install to compile the Open IMS C code:</p>
<ul>
<li>
<pre>sudo apt-get install gcc</pre>
</li>
<li>
<pre>sudo apt-get install bison</pre>
</li>
<li>
<pre>sudo apt-get install flex</pre>
</li>
<li>
<pre>sudo apt-get install curl</pre>
</li>
<li>
<pre>sudo apt-get install libxml2-dev</pre>
</li>
<li>
<pre>sudo apt-get install libmysql++-dev</pre>
</li>
<li>
<pre>sudo apt-get install libcurl4-gnutls-dev</pre>
</li>
<li>
<pre>sudo apt-get install bind9</pre>
</li>
</ul>
<p>For the Java code, I had to install the following:</p>
<ul>
<li>
<pre>sudo apt-get install ant</pre>
</li>
<li>
<pre>sudo apt-get install openjdk-6-jdk</pre>
</li>
</ul>
<p>To make my life a little easier, I added the following line to /etc/profile.d:</p>
<pre>      export JAVA_HOME=/usr/lib/jvm/java-6-openjdk/jre</pre>
<p>The last piece for this was configuring the bind. I hadn&#8217;t worked with bind before, so I struggled greatly with this. Apparently, I&#8217;m not the only one who struggled with this. Towards the bottom of the <a href="http://www.openimscore.org/installation_guide">Open Ims configuration document</a>, there&#8217;s an &#8220;Annex A&#8221; about how to configure bind. This helped, but there some differences between the configuration I ended up using and the configuration in the Annex.</p>
<p>Here&#8217;s the configurations I ended up using:</p>
<ul>
<li>
<pre>/etc/bind/named.conf.options:</pre>
<pre>options {
	directory "/var/cache/bind";

	// If there is a firewall between you and nameservers you want
	// to talk to, you may need to fix the firewall to allow multiple
	// ports to talk.  See http://www.kb.cert.org/vuls/id/800113

	// If your ISP provided one or more IP addresses for stable
	// nameservers, you probably want to use them as forwarders.
	// Uncomment the following block, and insert the addresses replacing
	// the all-0's placeholder.

        forward first;
	 forwarders {
	 	172.16.20.17;
	 };

	auth-nxdomain no;    # conform to RFC1035
	listen-on-v6 { any; };
};</pre>
</li>
<li>
<pre>/etc/bind/named.conf.default-zones:</pre>
<pre>// prime the server with knowledge of the root servers
zone "." {
	type hint;
	file "/etc/bind/db.root";
};

// be authoritative for the localhost forward and reverse zones, and for
// broadcast zones as per RFC 1912

zone "localhost" {
	type master;
	file "/etc/bind/db.local";
};

zone "127.in-addr.arpa" {
	type master;
	file "/etc/bind/db.127";
};

zone "0.in-addr.arpa" {
	type master;
	file "/etc/bind/db.0";
};

zone "255.in-addr.arpa" {
	type master;
	file "/etc/bind/db.255";
};
zone "open-ims.test" IN {
            type master;
            file "/etc/bind/open-ims.dnszone";
            notify no;
};

zone "172.in-addr.arpa" {
        type master;
        file "/etc/bind/db.172";
};</pre>
</li>
<li>
<pre>/etc/bind/db.172</pre>
<pre>ND reverse data file for local loopback interface
;
$TTL	 	604800
@	 	IN	SOA	open-ims.test. root.open-ims.test. (
			      4		; Serial
			 604800		; Refresh
			  86400		; Retry
			2419200		; Expire
			 604800 )	; Negative Cache TTL
;
@		IN	NS	open-ims.test.
82.20.16	IN	PTR	open-ims.test.
82.20.16	IN	PTR	pcscf
82.20.16 	IN	PTR	icscf
82.20.16 	IN	PTR	scscf
82.20.16 	IN	PTR	hss
82.20.16 	IN	PTR	ue
82.20.16 	IN	PTR	presence</pre>
</li>
<li>Don&#8217;t forget to copy over /opt/OpenIMS/ser_ims/cfg/open-ims.dnszone to /etc/bind and run the following commands to fix the permissions:
<pre>sudo chmod 644 open-ims.dnszone</pre>
<pre>sudo chown root:bind open-ims.dnszone</pre>
</li>
<li>
<pre>/etc/resolv.conf</pre>
<pre>nameserver 172.16.20.82
search open-ims.test
domain open-ims.test</pre>
</li>
<li>Last, restart bind:
<pre>sudo /etc/init.d/bind9 restart</pre>
</li>
</ul>
<p>After completing the Open IMS installation guide, with these modifications, I was able to start Open IMS and connect to the alice and bob users. Here&#8217;s the configuration I used for <a href="http://www.counterpath.com/x-lite-download.html">X-Lite 4</a> (with a password of &#8220;alice&#8221;):<br />
<img class="aligncenter size-full wp-image-407" src="http://blog.mersoft.com/wp-content/uploads/2012/03/Screen-Shot-2012-03-14-at-2.49.37-PM.png" alt="X-Lite 4 Configuration for Alice" width="527" height="573" /></p>
<p>The next step in setting up the environment for use with Mobicents Diameter was to set up and configure JBoss:</p>
<ul>
<li>Download JBoss from <a href="http://www.mobicents.org/mss-downloads.html">here</a>. Make sure you download the one that has Mobicents Diameter (I used the 1.5.0.Final with JBoss 5.1.0.GA-jdk6-full &#8212; I couldn&#8217;t get the 1.6.0.Final to download). NOTE: This is only available for JBoss. They do not have a Mobicents Diameter instance available for Tomcat as of this posting.</li>
<li>Unzip the JBoss server and set the $JBOSS_HOME environment variable.</li>
<li>Determine the version of the mobicents-diameter-MUX jar the server is using ($JBOSS_HOME/server/default/deploy/mobicents-diameter-mux-{version}.sar). The 1.3.3.Final is the version that came with 1.5.0.Final.</li>
<li>Check out the mobicents-diameter-mux from svn. To browse svn to make sure you get the right version, you can access it directly from <a href="http://mobicents.googlecode.com/svn/tags/servers/diameter/core/mux/">http://mobicents.googlecode.com/svn/tags/servers/diameter/core/mux/</a></li>
<li>Edit the following file
<pre>mobicents-diameter-mux-1.3.3.FINAL/sar-jboss-5/src/main/resources/config/jdiameter-config.xml</pre>
<p>with <a href="http://mobicents.googlecode.com/svn/trunk/servers/sip-servlets/sip-servlets-examples/diameter-openims/conf/mobicents-jdiameter/jdiameter-config.xml">this</a>.<br />
Be sure to use the IP of your JBoss Server here:</p>
<pre>&lt;LocalPeer&gt;
    ...
    &lt;IPAddresses&gt;
      &lt;IPAddress value="172.16.20.178" /&gt;
    &lt;/IPAddresses&gt;
    ...</pre>
<p>and the IP of your Open IMS server here:</p>
<pre>&lt;Network&gt;
    &lt;Peers&gt;
      &lt;Peer name="aaa://172.16.20.82:3868" attempt_connect="true" rating="1" /&gt;
    &lt;/Peers&gt;
    ...</pre>
</li>
<li>Run the following command to install the configured mobicents-diameter-mux:
<pre>mvn clean install</pre>
</li>
<li>Copy the <a href="http://www.mobicents.org/diameteropenims-dar.properties">diameteropenims-dar.properties</a> file to the following location:
<pre>$JBOSS_HOME/server/default/conf/dars/</pre>
</li>
<li>Edit the $JBOSS_HOME/server/default/deploy/jbossweb.sar/server.xml to point to the dars file:
<pre>   &lt;Server&gt;
    ...
   &lt;Service name="jboss.web"
        className="org.mobicents.servlet.sip.startup.SipStandardService"
        sipPathName="org.mobicents.ha"
                sipApplicationDispatcherClassName="org.mobicents.servlet.sip.core.SipApplicationDispatcherImpl"
                concurrencyControlMode="None"
                congestionControlCheckingInterval="-1"
                darConfigurationFileLocation="conf/dars/diameteropenims-dar.properties"
                sipStackPropertiesFile="conf/mss-sip-stack.properties"&gt;
     ...</pre>
</li>
</ul>
<p>Now you should be able to download and configure the Diameter-OpenIMS example from the example at the end of the document at <a href="http://www.mobicents.org/mss-diameter_sh.html">the Mobicents Diameter Sh</a> document. Remember, the origin.ip should be the IP address of the JBoss server and the destination.ip should be the IP address of the Open-IMS server.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.mersoft.com%2F2012%2F03%2F16%2Finstalling-and-configuring-open-ims-and-mobicents-diameter%2F&amp;linkname=Installing%20and%20Configuring%20Open%20IMS%20and%20Mobicents%20Diameter"><img src="http://blog.mersoft.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://blog.mersoft.com/2012/03/16/installing-and-configuring-open-ims-and-mobicents-diameter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twisting the Oreo for the Truth</title>
		<link>http://blog.mersoft.com/2012/03/09/twisting-the-oreo-for-the-truth/</link>
		<comments>http://blog.mersoft.com/2012/03/09/twisting-the-oreo-for-the-truth/#comments</comments>
		<pubDate>Fri, 09 Mar 2012 19:48:19 +0000</pubDate>
		<dc:creator>samsloop</dc:creator>
				<category><![CDATA[Information Technology]]></category>
		<category><![CDATA[Mersoft Team]]></category>
		<category><![CDATA[Party]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.mersoft.com/?p=401</guid>
		<description><![CDATA[How well do we know our Mersoft team? This question was asked today during our Oreo cookie celebration. We asked silly questions to get to know one another better and some interesting truths came out!
Who is a storm spotter in their spare time?

Carrolina Terrazas
Andy Beals
David Hepworth

Who used to be a  model?

Carrolina Terrazas
Andy Beals
David Hepworth

Whose favorite [...]]]></description>
			<content:encoded><![CDATA[<p>How well do we know our <a title="Mersoft.com" href="http://www.mersoft.com" target="_blank">Mersoft</a> team? This question was asked today during our Oreo cookie celebration. We asked silly questions to get to know one another better and some interesting truths came out!</p>
<p>Who is a storm spotter in their spare time?</p>
<ol>
<li>Carrolina Terrazas</li>
<li>Andy Beals</li>
<li>David Hepworth</li>
</ol>
<p>Who used to be a  model?</p>
<ol>
<li>Carrolina Terrazas</li>
<li>Andy Beals</li>
<li>David Hepworth</li>
</ol>
<p>Whose favorite cartoon is Roadrunner?</p>
<ol>
<li>Carrolina Terrazas</li>
<li>Andy Beals</li>
<li>David Hepworth</li>
</ol>
<p>Need help? Read the Bio’s below to get to know our team a little bit better!</p>
<p><strong>Andy Beals</strong></p>
<p>Andy Beals is over IT at<a title="Mersoft.com" href="http://www.mersoft.com" target="_blank"> Mersoft</a>. His favorite part about working for the company is that he gets to do a lot of different things. Half of the week he is at the office but the other half he does IT at a school called Ascension. During Andy’s free time he enjoys storm spotting. He has been interested in the trade for up to 20 years now and as of last year found a local group where he was trained to be an official storm spotter.</p>
<p>To learn more about our IT Department<a class="wp-caption" title="Mersoft Technology" href="http://mersoft.com/technology" target="_blank"><span class="wp-caption">click here </span></a></p>
<p><strong>David Hepworth</strong></p>
<p>David Hepworth works at <a title="Mersoft.com" href="http://www.mersoft.com" target="_blank">Mersoft</a> as the office manager. However, in his free time he is a genealogy extractioner. One of his greatest accomplishments in life is his family. He has been happily married for 40 years and has 5 children and 13 grandchildren. A fun fact that people don’t normally know about David is that he used to be a model. His favorite part about working for <a title="Mersoft.com" href="http://www.mersoft.com" target="_blank">Mersoft</a> is that he gets to work with smart, all around good people.</p>
<p><strong> </strong></p>
<p><strong>Carrolina Terrazas</strong></p>
<p>Carrolina Terrazas is a sales associate at <a title="Mersoft.com" href="http://www.mersoft.com" target="_blank">Mersoft</a>. She enjoys playing video games , going to the gym and reading in her free time. Her favorite cartoon is Roadrunner because he was always getting into trouble and it was the first cartoon she watched as a kid. One of her greatest accomplishments was recently when she paid off her car! Her favorite thing about working for <a title="Mersoft.com" href="http://www.mersoft.com" target="_blank">Mersoft</a> is that she is able to not only do sales, but also marketing and account management.</p>
<p>Shocked? So were we. Can&#8217;t wait for the next party!</p>
<p><em>To view our pictures from our Oreo party and connect with other Mersoft happenings</em> <a class="wp-caption" title="Facebook" href="www.Facebook.com/Mersoft" target="_blank">click here</a></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.mersoft.com%2F2012%2F03%2F09%2Ftwisting-the-oreo-for-the-truth%2F&amp;linkname=Twisting%20the%20Oreo%20for%20the%20Truth"><img src="http://blog.mersoft.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://blog.mersoft.com/2012/03/09/twisting-the-oreo-for-the-truth/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting started with Drools 5.2</title>
		<link>http://blog.mersoft.com/2011/09/07/getting-started-with-drools-5-2/</link>
		<comments>http://blog.mersoft.com/2011/09/07/getting-started-with-drools-5-2/#comments</comments>
		<pubDate>Wed, 07 Sep 2011 15:13:56 +0000</pubDate>
		<dc:creator>Mandi Zinn</dc:creator>
				<category><![CDATA[Java/Java Frameworks]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[drools]]></category>
		<category><![CDATA[drools maven]]></category>
		<category><![CDATA[drools spring]]></category>
		<category><![CDATA[stateful session]]></category>
		<category><![CDATA[stateless session]]></category>

		<guid isPermaLink="false">http://blog.mersoft.com/?p=372</guid>
		<description><![CDATA[When I was attempting to learn Drools, I found it difficult to find a good tutorial. I also had a hard time figuring out how to use the rules engine in a stateless, thread-save manner. This tutorial discusses how to set up Drools in Eclipse, how to write the rules, how to execute the rules, [...]]]></description>
			<content:encoded><![CDATA[<p>When I was attempting to learn Drools, I found it difficult to find a good tutorial. I also had a hard time figuring out how to use the rules engine in a stateless, thread-save manner. This tutorial discusses how to set up Drools in Eclipse, how to write the rules, how to execute the rules, how to call methods outside the rules engine, how to use the rules-flow, how to use Drools with Maven2 and how to configure the Drools knowledge base using Spring.</p>
<p><strong>Setting up Drools in Eclipse:</strong></p>
<p>After downloading and setting up Eclipse.</p>
<ul>
<li>Start up eclipse and go to Help-&gt;Install New Software.</li>
<li>In the &#8220;Work with&#8221; box, enter &#8220;http://download.jboss.org/jbosstools/updates/stable/&#8221;.</li>
<li>Expand the &#8220;All Jboss Tools&#8221; and mark &#8220;JBoss Drools Core&#8221;, &#8220;JBoss Drools Guvnor&#8221;, and &#8220;JBoss Drools Task&#8221; for installation.</li>
<li>Finish the installation and allow Eclipse to restart.</li>
<li>Open up the Eclipse preferences and go to Drools -&gt; Installed Drools Runtime.</li>
<li>Select the &#8220;Add&#8221; button.</li>
<li>Select the &#8220;Create a new Drools 5 Runtime&#8221;.</li>
<li>Choose a location for the Drools 5 runtime and select &#8220;OK&#8221;.</li>
<li>Select the newly created runtime and select &#8220;OK&#8221; and restart Eclipse.</li>
</ul>
<p><strong>First Drools project in Eclipse:</strong></p>
<p>To create a drools project in Eclipse:</p>
<ul>
<li>Select File -&gt; New -&gt; Other.</li>
<li>Under Drools, select &#8220;Drools Project&#8221;.</li>
<li>Select &#8220;next&#8221; and enter a project name.</li>
<li>Select &#8220;next&#8221;. Leave the default boxes checked and select &#8220;next&#8221;.</li>
<li>Under &#8220;Generate code compatible with&#8221; make sure the &#8220;Drools 5.1 or above&#8221; is selected. Select &#8220;Finish&#8221;</li>
</ul>
<p>This will give you a sample &#8220;Hello World&#8221; application. Let&#8217;s look at the pieces:</p>
<p>1. In src/main/rules, open Sample.drl. Here&#8217;s the contents of Sample.drl:</p>
<pre>    package com.sample

    import com.sample.DroolsTest.Message;

    rule "Hello World"
        when
            m : Message( status == Message.HELLO, myMessage : message )
        then
            System.out.println( myMessage );
            m.setMessage( "Goodbye cruel world" );
            m.setStatus( Message.GOODBYE );
            update( m );
    end

    rule "GoodBye"
        when
            Message( status == Message.GOODBYE, myMessage : message )
        then
            System.out.println( myMessage );
    end</pre>
<p>This file contains two rules: &#8220;Hello World&#8221; and &#8220;GoodBye&#8221;.</p>
<ul>
<li>The &#8220;Hello World&#8221; rule says that for every Message in the knowledge base session (don&#8217;t worry about this yet, I&#8217;ll explain this below) that contains a status of <em>Message.HELLO</em>, assign that object to variable <em>m</em> and assign the message to the variable <em>myMessage.</em> If the system successfully assigns one or more <em>m</em> variables, then print the message to system out, set a new message, change the status to <em>Message.GOODBYE</em> and update the object in the session.</li>
<li>The &#8220;GoodBye&#8221; rule says that for every Message in the knowledge base that contains a status of <em>Message.GOODBYE</em>, assign the message to the variable <em>myMessage</em> then print the message to system out.</li>
<li>These rules are evaluated when the objects are inserted or updated. In this case, inserting the initial message will trigger the &#8220;Hello World&#8221; rule since the status is <em>Message.HELLO</em>. The &#8220;GoodBye&#8221; rule conditions will be false, so it will be skipped. After the &#8220;Hello World&#8221; rule updates the Message in the session, both the &#8220;Hello World&#8221; rule and the &#8220;GoodBye&#8221; rules will be re-evaluated. In this case, the &#8220;Hello World&#8221; rule conditions will be false so it will be skipped and the &#8220;GoodBye&#8221; conditions will be true so it will be executed.</li>
</ul>
<p>2. In src/main/java, open com.sample.DroolsTest. Here&#8217;s the steps:</p>
<div style="padding-left: 10px">a. Create the Knowledge Base:</div>
<div style="padding-left: 15px">The Knowledge Base holds all the rules. From the knowledge base, you create a session and insert all the objects (also called facts). The facts are what the rules are executed against.</div>
<div style="padding-left: 15px">Here&#8217;s how this class generates the Knowledge Base:</div>
<pre>        private static KnowledgeBase readKnowledgeBase() throws Exception {
            KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
            kbuilder.add(ResourceFactory.newClassPathResource("Sample.drl"), ResourceType.DRL);
            KnowledgeBuilderErrors errors = kbuilder.getErrors();
            if (errors.size() &gt; 0) {
                for (KnowledgeBuilderError error: errors) {
        	    System.err.println(error);
                }
                throw new IllegalArgumentException("Could not parse knowledge.");
            }
            KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
            kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
            return kbase;
        }</pre>
<p>In this method we load our drools files (in this case, we only have one: Sample.drl), and build our knowledge base.</p>
<div style="padding-left: 10px">b. Create a Stateful Knowledge Session (Drools offers both a stateful and a stateless session. From what I can tell, the difference between the two is that the stateless session has a different memory manager, but still uses a stateful session under the hood. I have not seen any benefit from the stateless session, and it appears the stateful is better supported than the stateless):</div>
<pre>        KnowledgeBase kbase = readKnowledgeBase();
        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();</pre>
<div style="padding-left: 10px">c. Insert the facts into the session:</div>
<pre>            Message message = new Message();
            message.setMessage("Hello World");
            message.setStatus(Message.HELLO);
            ksession.insert(message);</pre>
<div style="padding-left: 10px">d. Execute the rules:</div>
<pre>           ksession.fireAllRules();</pre>
<p><strong>Sample System</strong><br />
For the purposes Mersoft has needed a Drools engine, the engine must be thread-safe and stateless. The system needs to insert the facts, execute the rules, process the results and repeat without any knowledge of the previous facts. To demonstrate this, we are going to build a system to figure the state&#8217;s sales tax for Kansas and Missouri.</p>
<p>Let&#8217;s start with a model to hold each item being purchased:</p>
<pre>        package com.sample.model;

        import java.math.BigDecimal;

        public class SaleItem {
        	public enum State {
        		KANSAS, MISSOURI
        	}

        	public enum Type {
        		FOOD, PRESCRIPTION_MEDICATION, NON_PRESCRIPTION_MEDICATION, NON_FOOD_NON_MEDICATION_ITEM
        	}

        	private State purchaseState;
	        private BigDecimal salesPrice;
        	private Type itemType;
	        private BigDecimal stateTax;

        	public State getPurchaseState() {
        		return purchaseState;
        	}
        	public void setPurchaseState(State purchaseState) {
        		this.purchaseState = purchaseState;
        	}
        	public BigDecimal getSalesPrice() {
        		return salesPrice;
        	}
        	public void setSalesPrice(BigDecimal salesPrice) {
        		this.salesPrice = salesPrice;
        	}
        	public Type getItemType() {
        		return itemType;
        	}
        	public void setItemType(Type itemType) {
        		this.itemType = itemType;
        	}
        	public BigDecimal getStateTax() {
        		return stateTax;
        	}
        	public void setStateTax(BigDecimal stateTax) {
        		this.stateTax = stateTax;
        	}

        }</pre>
<p>Since the state sales tax is being determined by the state and the purchase type, I have created these as enumerations. For our rules, we will create our rules with the understanding that the purchaseState, salesPrice, and itemType will be populated and the rules will populate the stateTax.</p>
<p>Now for our rules. Let&#8217;s start with the sales tax from Kansas. Kansas state sales tax is calculated as 6.3% of the purchase with an exemption for prescription medication.</p>
<p>Let&#8217;s create a new rules file specifically for calculating the Kansas state sales tax.</p>
<ul>
<li>In Eclipse, right-click on the src/main/rules folder and select New -&gt; Other. Select Drools -&gt; Rule Resource.</li>
<li>After selecting &#8220;Next&#8221; enter &#8220;KansasSalesTax&#8221; as the file name and &#8220;com.sample&#8221; as the package name and select &#8220;Finish&#8221;.</li>
</ul>
<p><strong>Things to note:</strong>,</p>
<ul>
<li>Any Java objects used, must be declared as an import (unfortunately, Eclipse will not manage these for you).</li>
<li>Code used in the <em>when</em> clause, must use the Drools language.</li>
<li>Every condition in the <em>when</em> clause must evaluate to true to execute the <em>then</em> clause.</li>
<li>Code in the <em>then</em> clause is pure Java code.</li>
<li>The colon (:) in the <em>when</em> clause is for assignment.</li>
<li>If an assignment fails, the <em>when</em> clause evaluates to false.</li>
<li>Use the <em>eval</em> method to determine if something is equal or is true or false via Java.</li>
</ul>
<p>First, let&#8217;s create a rule for calculating the sales tax for the state of Kansas for non-prescription medication items:</p>
<pre>	package com.sample

	import com.sample.model.SaleItem;
	import java.math.BigDecimal;

	rule "Kansas non-prescription medication item"
	    when
		item : SaleItem(purchaseState == SaleItem.State.KANSAS, itemType != SaleItem.Type.PRESCRIPTION_MEDICATION)
	    then
		BigDecimal tax = new BigDecimal(.063);
		item.setStateTax(tax.multiply(item.getSalesPrice()));
	end</pre>
<p>Notice our when clause has two items it&#8217;s using to evaluate the item. To trigger this rule, both these conditions must be met.</p>
<p>Here&#8217;s the rule for calculating the sales tax for the prescription medication:</p>
<pre>	rule "Kansas prescription medication item"
	    when
		item : SaleItem(purchaseState == SaleItem.State.KANSAS, itemType == SaleItem.Type.PRESCRIPTION_MEDICATION)
	    then
		item.setStateTax(new BigDecimal(0));
	end</pre>
<p>The sales tax in Missouri is 4.225% of the purchase with an exemption for prescription medication. Also, if the item is a food item, the sales tax is 1.225%. Here&#8217;s our rules for Missouri (MissouriSalesTax.drl):</p>
<pre>	package com.sample

	import com.sample.model.SaleItem;
	import java.math.BigDecimal;

	rule "Missouri non-prescription medication, non-food item"
	    when
		item : SaleItem(purchaseState == SaleItem.State.MISSOURI, itemType != SaleItem.Type.PRESCRIPTION_MEDICATION, itemType != SaleItem.Type.FOOD)
	    then
		BigDecimal tax = new BigDecimal(0.04225);
		item.setStateTax(tax.multiply(item.getSalesPrice()));

	end

	rule "Missouri prescription medication item"
	    when
		item : SaleItem(purchaseState == SaleItem.State.MISSOURI, itemType == SaleItem.Type.PRESCRIPTION_MEDICATION)
	    then
		item.setStateTax(new BigDecimal(0));
	end

	rule "Missouri food item"
	    when
		item : SaleItem(purchaseState == SaleItem.State.MISSOURI, itemType == SaleItem.Type.FOOD)
	    then
		BigDecimal tax = new BigDecimal(0.01225);
		item.setStateTax(tax.multiply(item.getSalesPrice()));
	end</pre>
<p>Let&#8217;s run a test and verify we received the correct amounts:</p>
<pre>        package com.sample;

        import java.math.BigDecimal;

        import org.drools.KnowledgeBase;
        import org.drools.KnowledgeBaseFactory;
        import org.drools.builder.KnowledgeBuilder;
        import org.drools.builder.KnowledgeBuilderError;
        import org.drools.builder.KnowledgeBuilderErrors;
        import org.drools.builder.KnowledgeBuilderFactory;
        import org.drools.builder.ResourceType;
        import org.drools.io.ResourceFactory;
        import org.drools.runtime.StatefulKnowledgeSession;

        import com.sample.model.SaleItem;
        import com.sample.model.SaleItem.State;
        import com.sample.model.SaleItem.Type;

        public class SalesTaxTest {

            public static final void main(String[] args) {
                try {
                    // load up the knowledge base
                    KnowledgeBase kbase = readKnowledgeBase();
                    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();

                    //Non-prescription item
                    //Expect $1.89 for the tax
                    SaleItem item1 = new SaleItem();
                    item1.setPurchaseState(State.KANSAS);
                    item1.setItemType(Type.FOOD);
                    item1.setSalesPrice(new BigDecimal(29.95));
                    ksession.insert(item1);

                    //Prescription item
                    //Expect $0 for the tax
                    SaleItem item2 = new SaleItem();
                    item2.setPurchaseState(State.KANSAS);
                    item2.setItemType(Type.PRESCRIPTION_MEDICATION);
                    item2.setSalesPrice(new BigDecimal(29.95));
                    ksession.insert(item2);

                    //Non-prescription, non-food item
                    //Expect $1.27 for the tax
                    SaleItem item3 = new SaleItem();
                    item3.setPurchaseState(State.MISSOURI);
                    item3.setItemType(Type.NON_FOOD_NON_MEDICATION_ITEM);
                    item3.setSalesPrice(new BigDecimal(29.95));
                    ksession.insert(item3);

                    //Prescription item
                    //Expect $0 for the tax
                    SaleItem item4 = new SaleItem();
                    item4.setPurchaseState(State.MISSOURI);
                    item4.setItemType(Type.PRESCRIPTION_MEDICATION);
                    item4.setSalesPrice(new BigDecimal(29.95));
                    ksession.insert(item4);

                    //Food item
                    //Expect $0.37 for the tax
                    SaleItem item5 = new SaleItem();
                    item5.setPurchaseState(State.MISSOURI);
                    item5.setItemType(Type.FOOD);
                    item5.setSalesPrice(new BigDecimal(29.95));
                    ksession.insert(item5);

                    ksession.fireAllRules();

                    System.out.println(item1.getPurchaseState().toString() + " " + item1.getItemType().toString() + ": " + item1.getStateTax().toString());
                    System.out.println(item2.getPurchaseState().toString() + " " + item2.getItemType().toString() + ": " + item2.getStateTax().toString());
                    System.out.println(item3.getPurchaseState().toString() + " " + item3.getItemType().toString() + ": " + item3.getStateTax().toString());
                    System.out.println(item4.getPurchaseState().toString() + " " + item4.getItemType().toString() + ": " + item4.getStateTax().toString());
                    System.out.println(item5.getPurchaseState().toString() + " " + item5.getItemType().toString() + ": " + item5.getStateTax().toString());

                } catch (Throwable t) {
                    t.printStackTrace();
                }
            }

            private static KnowledgeBase readKnowledgeBase() throws Exception {
                KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
                kbuilder.add(ResourceFactory.newClassPathResource("KansasSalesTax.drl"), ResourceType.DRL);
                kbuilder.add(ResourceFactory.newClassPathResource("MissouriSalesTax.drl"), ResourceType.DRL);
                KnowledgeBuilderErrors errors = kbuilder.getErrors();
                if (errors.size() &gt; 0) {
                    for (KnowledgeBuilderError error: errors) {
                        System.err.println(error);
                    }
                    throw new IllegalArgumentException("Could not parse knowledge.");
                }
                KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
                kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
                return kbase;
            }

        }</pre>
<p><strong>Executing methods outside of Drools</strong></p>
<p>When using the Drools engine, I have found it necessary to be able to access methods accessing a database. I have also found it convenient to access static methods that are commonly used, such as an error handler.</p>
<p>To use a static method, simply declare the class in the imports and use it in a static manner.</p>
<p>Here&#8217;s an example:</p>
<pre>        package com.sample;

        public class HelloSayer {

        	public static void sayHello(String name) {
        		System.out.println("HELLO " + name + "!!!");
        	}
        }</pre>
<p>To use this within Drools, add this import:</p>
<pre>        import com.sample.HelloSayer;</pre>
<p>Update the rule:</p>
<pre>        rule "Kansas non-prescription medication item"
            when
                item : SaleItem(purchaseState == SaleItem.State.KANSAS, itemType != SaleItem.Type.PRESCRIPTION_MEDICATION)
            then
    	        BigDecimal tax = new BigDecimal(.063);
    	        item.setStateTax(tax.multiply(item.getSalesPrice()));
            	HelloSayer.sayHello(item.getPurchaseState().toString());
        end</pre>
<p>Another way of accessing methods outside drools is to declare a global variable. Here&#8217;s the method I want to access:</p>
<pre>        package com.sample;

        public class AnotherHello {
	        public String getHelloLine(String name) {
		        return "Hello " + name + "!!!!";
	        }
        }</pre>
<p>To access this in the rule, I need to import the class and declare the global object:</p>
<pre>        import com.sample.AnotherHello;

        global AnotherHello anotherHello;</pre>
<p>Here&#8217;s the updated rule:</p>
<pre>        rule "Kansas prescription medication item"
            when
                item : SaleItem(purchaseState == SaleItem.State.KANSAS, itemType == SaleItem.Type.PRESCRIPTION_MEDICATION)
            then
    	        item.setStateTax(new BigDecimal(0));
    	        System.out.println(anotherHello.getHelloLine(item.getPurchaseState().toString()));
        end</pre>
<p>Lastly, you need to set the global object into the knowledge base session:</p>
<pre>            ksession.setGlobal("anotherHello", new AnotherHello());</pre>
<p><strong>Using Drools rules flow</strong></p>
<p>The Drools rules are executed in no particular order. There are two ways to order rules: salience, and rules flow.</p>
<ul>
<li>For salience, you declare <em>salience</em> above the rule&#8217;s where clause and give a value. The higher the value the earlier the rule will be executed.</li>
<li>For the rules flow, you declare a <em>rule-flow group </em>for each rule and then you provide a rules flow file to indicate the flow of the rules.</li>
</ul>
<p>For this example, we&#8217;ll use both salience and the rules flow.</p>
<p>For our sales tax, let&#8217;s adjust the rules so that we can print out the total state tax after all the rules have executed. Let&#8217;s also create an object to store the total tax in case we would like to retrieve this for use outside the rules engine.</p>
<p>Here&#8217;s our Tax item:</p>
<pre>        package com.sample.model;

        import java.math.BigDecimal;

        public class Tax {

        	private BigDecimal totalTax = new BigDecimal(0);

	        public BigDecimal getTotalTax() {
		        return totalTax;
	        }

        	public void setTotalTax(BigDecimal totalTax) {
	        	this.totalTax = totalTax;
	        }

	        public void addTax(BigDecimal tax) {
		        totalTax = totalTax.add(tax);
	        }
        }</pre>
<p>Let&#8217;s make the <em>Tax</em> item available to all the rules so we can easily add the tax as it is being calculated. Here&#8217;s the new rules file (SalesTax.drl):</p>
<pre>        package com.sample

        import com.sample.model.Tax;
        import java.math.BigDecimal;

        rule "Add Sales Tax Calculation"
	        ruleflow-group "taxItem"
            when
    	        not (Tax())
            then
    	        insert(new Tax());
        end

        rule "Print final sales tax"
	        ruleflow-group "finished"
	        when
		        tax : Tax()
	        then
		        System.out.println("Total taxes: $" + tax.getTotalTax().setScale(2).toString());
        end</pre>
<ul>
<li>Here the ruleflow-group determines when these rules are executing.</li>
<li>The &#8220;Add Sales Tax Calculation&#8221; will be executed when the <em>taxItem</em> rules are executed and the &#8220;Print final sales tax&#8221; will be executed when the <em>finished</em> rules are executed. We&#8217;ll tell drools when to execute each group below.</li>
</ul>
<p>Let&#8217;s update the other rules to also have a rule-flow group of <em>calculation</em>. Also, let&#8217;s say that for some reason the &#8220;Kansas non-prescription medication item&#8221; rule needs to run before the other rules. We&#8217;ll accomplish this by using salience. Here&#8217;s the updated KansasSalesTax.drl:</p>
<pre>        package com.sample

        import com.sample.model.SaleItem;
        import com.sample.model.Tax;
        import java.math.BigDecimal;
        import com.sample.HelloSayer;
        import com.sample.AnotherHello;

        global AnotherHello anotherHello;

        rule "Kansas non-prescription medication item"
	        ruleflow-group "calculation"
        	salience 5
            when
                item : SaleItem(purchaseState == SaleItem.State.KANSAS, itemType != SaleItem.Type.PRESCRIPTION_MEDICATION)
                totalTax : Tax()
            then
    	        BigDecimal tax = new BigDecimal(.063);
            	item.setStateTax(tax.multiply(item.getSalesPrice()));
    	        HelloSayer.sayHello(item.getPurchaseState().toString());
            	totalTax.addTax(item.getStateTax());

        end

        rule "Kansas prescription medication item"
	        ruleflow-group "calculation"
            when
                item : SaleItem(purchaseState == SaleItem.State.KANSAS, itemType == SaleItem.Type.PRESCRIPTION_MEDICATION)
                totalTax : Tax()
            then
    	        item.setStateTax(new BigDecimal(0));
            	System.out.println(anotherHello.getHelloLine(item.getPurchaseState().toString()));
    	        totalTax.addTax(item.getStateTax());
        end</pre>
<p>Here&#8217;s the updated MissouriSalesTax.drl:</p>
<pre>        package com.sample

        import com.sample.model.SaleItem;
        import com.sample.model.Tax;
        import java.math.BigDecimal;

        rule "Missouri non-prescription medication, non-food item"
	        ruleflow-group "calculation"
            when
                item : SaleItem(purchaseState == SaleItem.State.MISSOURI, itemType != SaleItem.Type.PRESCRIPTION_MEDICATION, itemType != SaleItem.Type.FOOD)
                totalTax : Tax()
            then
    	        BigDecimal tax = new BigDecimal(0.04225);
            	item.setStateTax(tax.multiply(item.getSalesPrice()));
            	totalTax.addTax(item.getStateTax());

        end

        rule "Missouri prescription medication item"
	        ruleflow-group "calculation"
            when
                item : SaleItem(purchaseState == SaleItem.State.MISSOURI, itemType == SaleItem.Type.PRESCRIPTION_MEDICATION)
                totalTax : Tax()
            then
    	        item.setStateTax(new BigDecimal(0));
            	totalTax.addTax(item.getStateTax());
        end

        rule "Missouri food item"
	        ruleflow-group "calculation"
            when
                item : SaleItem(purchaseState == SaleItem.State.MISSOURI, itemType == SaleItem.Type.FOOD)
                totalTax : Tax()
            then
    	        BigDecimal tax = new BigDecimal(0.01225);
            	item.setStateTax(tax.multiply(item.getSalesPrice()));
    	        totalTax.addTax(item.getStateTax());
        end</pre>
<p>Now we need to create our Rules Flow.</p>
<ul>
<li>In Eclipse, right-click on src/main/rules, select New -&gt; Other.</li>
<li>Select Drools -&gt; Flow File and hit &#8220;Next&#8221;.</li>
<li>Enter rulesFlow as the file name and hit &#8220;Next&#8221;.</li>
<li>Change the &#8220;Generate code compatible with&#8221; to be &#8220;5.1.x&#8221; and select &#8220;Finished&#8221;. <strong>Note</strong>: when I upgraded from 5.1 to 5.2.0.Final, I noticed I could not use the 5.0.x rules flow without the knowledge base erring out. The rules flow for the 5.0 and 5.1 have changed drastically, and I believe they have removed the 5.0 compatibility from the 5.2.0.Final libraries.</li>
</ul>
<p><strong>Notes</strong>:</p>
<ul>
<li>Every rules flow has a start event and an end event.</li>
<li>The <em>Rule Task</em> component tells the rules flow which group to execute.</li>
<li>The <em>Gateway diverge</em> component will take in the output from one rule task and split into multiple paths.</li>
<li>The <em>Gateway converge</em> component will take in multiple paths and combine them to one path.</li>
<li>For this example, I will not be using the <em>Gateway diverge</em> or <em>Gateway converge</em>.</li>
</ul>
<p>The rules flow should start out looking like this:</p>
<p><img class="alignnone size-full wp-image-373" src="http://blog.mersoft.com/wp-content/uploads/2011/09/Screen-shot-2011-09-06-at-2.10.29-PM.png" alt="Screen shot 2011-09-06 at 2.10.29 PM" width="480" height="541" /></p>
<ul>
<li>Click on &#8220;Rule Task&#8221; on the left hand side and click again under the &#8220;Start Event&#8221; indicator on the right hand side.</li>
<li>This is for the &#8220;taxItem&#8221; group.</li>
<li>The editing of these items is not very intuitive. In Eclipse, you need to have the &#8220;Properties&#8221; window open.</li>
<li>With the Rule task selected, you can edit the &#8220;RuleFlowGroup&#8221; (this must be the ruleflow-group name we used above: <em>taxItem</em>) and the Name (I used <em>TaxItem</em>).</li>
<li>Add the remaining rule tasks (next <em>calculation</em>, then <em>finished</em>).</li>
<li>Add the end event.</li>
<li>Select &#8220;Sequence Flow&#8221; and click from one item to the next until the arrows connect all the items.</li>
</ul>
<p>When you&#8217;re finished, it should look like this:</p>
<p><img class="alignnone size-full wp-image-374" src="http://blog.mersoft.com/wp-content/uploads/2011/09/Screen-shot-2011-09-06-at-2.17.23-PM.png" alt="Screen shot 2011-09-06 at 2.17.23 PM" width="382" height="404" /></p>
<p>The last thing to do with the rules flow is to give it an <em>id</em> and a <em>package</em>.</p>
<ul>
<li>Select the &#8220;Select&#8221; on the left hand side and click on a blank portion of the right hand side of the rules flow.</li>
<li>In the properties view, you should be able to edit these properties for the rules flow.</li>
<li>Use <em>taxflow</em> for the <em>id</em> and <em>com.sample</em> for the <em>package</em>. Be sure to save the file.</li>
</ul>
<p>We return to our SalesTaxTest.java and update the &#8220;readKnowledgeBase&#8221; method as follows:</p>
<pre>            private static KnowledgeBase readKnowledgeBase() throws Exception {
                KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
                kbuilder.add(ResourceFactory.newClassPathResource("rulesFlow.bpmn"), ResourceType.BPMN2);
                kbuilder.add(ResourceFactory.newClassPathResource("KansasSalesTax.drl"), ResourceType.DRL);
                kbuilder.add(ResourceFactory.newClassPathResource("MissouriSalesTax.drl"), ResourceType.DRL);
                kbuilder.add(ResourceFactory.newClassPathResource("SalesTax.drl"), ResourceType.DRL);
                KnowledgeBuilderErrors errors = kbuilder.getErrors();
                if (errors.size() &gt; 0) {
                    for (KnowledgeBuilderError error: errors) {
                        System.err.println(error);
                    }
                    throw new IllegalArgumentException("Could not parse knowledge.");
                }
                KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
                kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
                return kbase;
            }</pre>
<p>Also, we need to tell Drools which process to start, so in the main method, before firing all the rules, add the following line to the main method:</p>
<pre>        ksession.startProcess("taxflow");</pre>
<p>Execute the rules. Here&#8217;s the output I received:</p>
<pre>        HELLO KANSAS!!!
        Hello KANSAS!!!!
        Total taxes: $3.52
        KANSAS FOOD: 1.886849999999999968536279482123063328849916437901430179058573886885508130717425956390798091888427734375
        KANSAS PRESCRIPTION_MEDICATION: 0
        MISSOURI NON_FOOD_NON_MEDICATION_ITEM: 1.265387500000000054770077362320533018853500952510289266498408528895114333323590471991337835788726806640625
        MISSOURI PRESCRIPTION_MEDICATION: 0
        MISSOURI FOOD: 0.3668875000000000054276028116362337017301445984489805027497347548158523888872650786652229726314544677734375</pre>
<p><strong>Using Drools with Maven</strong></p>
<p>Since the Drools libraries are a collection of jars, it can easily be used with Maven. Here&#8217;s the pom.xml for the system we&#8217;ve been discussing:</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;

    &lt;groupId&gt;com.sample&lt;/groupId&gt;
    &lt;artifactId&gt;HelloDrools&lt;/artifactId&gt;
    &lt;packaging&gt;jar&lt;/packaging&gt;
    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;

    &lt;name&gt;Sample Drools Project&lt;/name&gt;

    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.jbpm&lt;/groupId&gt;
            &lt;artifactId&gt;jbpm-bpmn2&lt;/artifactId&gt;
            &lt;version&gt;5.1.0.Final&lt;/version&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;

    &lt;build&gt;
        &lt;resources&gt;
            &lt;resource&gt;
                &lt;directory&gt;src/main/resources&lt;/directory&gt;
            &lt;/resource&gt;
            &lt;resource&gt;
                &lt;directory&gt;src/main/rules&lt;/directory&gt;
            &lt;/resource&gt;
        &lt;/resources&gt;
    &lt;/build&gt;
&lt;/project&gt;</pre>
<p>Note: Although there are lots of dependencies needed for this project, I have discovered that if you pull in this one dependency, it will pull in the other dependencies you need.</p>
<p>In the Eclipse environment, we use the m2eclipse plugin. Once we convert the project to a maven project, we simply remove the &#8220;Drools Library&#8221; from the build path and that ensures the maven dependencies are being used properly and prevents library conflicts. To use the Drools tools that Eclipse provides, you must keep the &#8220;Drools Project&#8221; configuration.</p>
<p><strong>Using Spring to generate the Knowledge base.</strong></p>
<p>Starting with Drools 5.1, JBoss has provided to ability to configure the Knowledge base via Spring. To do this, add the drools-spring library along with the Spring libraries. Here&#8217;s the updated pom.xml:</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;

    &lt;groupId&gt;com.sample&lt;/groupId&gt;
    &lt;artifactId&gt;HelloDrools&lt;/artifactId&gt;
    &lt;packaging&gt;jar&lt;/packaging&gt;
    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;

    &lt;name&gt;Sample Drools Project&lt;/name&gt;

    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.jbpm&lt;/groupId&gt;
            &lt;artifactId&gt;jbpm-bpmn2&lt;/artifactId&gt;
            &lt;version&gt;5.1.0.Final&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.drools&lt;/groupId&gt;
            &lt;artifactId&gt;drools-spring&lt;/artifactId&gt;
            &lt;version&gt;5.2.0.Final&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework&lt;/groupId&gt;
            &lt;artifactId&gt;spring-core&lt;/artifactId&gt;
            &lt;version&gt;3.0.5.RELEASE&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework&lt;/groupId&gt;
            &lt;artifactId&gt;spring-beans&lt;/artifactId&gt;
            &lt;version&gt;3.0.5.RELEASE&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework&lt;/groupId&gt;
            &lt;artifactId&gt;spring-context&lt;/artifactId&gt;
            &lt;version&gt;3.0.5.RELEASE&lt;/version&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;

    &lt;build&gt;
        &lt;resources&gt;
            &lt;resource&gt;
                &lt;directory&gt;src/main/resources&lt;/directory&gt;
            &lt;/resource&gt;
            &lt;resource&gt;
                &lt;directory&gt;src/main/rules&lt;/directory&gt;
            &lt;/resource&gt;
        &lt;/resources&gt;
    &lt;/build&gt;
&lt;/project&gt;</pre>
<p>Now we need to add the Spring configuration. Under src/main/resources, I created droolsContext.xml:</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:drools="http://drools.org/schema/drools-spring"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://drools.org/schema/drools-spring http://drools.org/schema/drools-spring-1.3.0.xsd"&gt;

  &lt;drools:grid-node id="node1"/&gt;

  &lt;drools:kbase id="kbase1" node="node1"&gt;
      &lt;drools:resources&gt;
      &lt;drools:resource type="BPMN2" source="classpath:rulesFlow.bpmn"/&gt;
      &lt;drools:resource type="DRL" source="classpath:KansasSalesTax.drl"/&gt;
      &lt;drools:resource type="DRL" source="classpath:MissouriSalesTax.drl"/&gt;
      &lt;drools:resource type="DRL" source="classpath:SalesTax.drl"/&gt;
    &lt;/drools:resources&gt;
  &lt;/drools:kbase&gt;

&lt;/beans&gt;</pre>
<p>I have not used the grid-node in any other form than above. I&#8217;m not sure it&#8217;s purpose, but it is required to generate the knowledge base. Notice that we&#8217;re including all the files we included when we created the knowledge base in code.</p>
<p>Now in our SalesTaxTest class, we can update readKnowledgeBase to be as follows:</p>
<pre>        private static KnowledgeBase readKnowledgeBase() throws Exception {
    	        ClassPathXmlApplicationContext serviceContext = new ClassPathXmlApplicationContext( "droolsContext.xml" );
		return (KnowledgeBase) serviceContext.getBean("kbase1");
        }</pre>
<p><strong>Note:</strong> I have used Drools spring to create the knowledge base session, however, Spring creates a singleton by default and the drools-spring plugin does not allow you to override that. So, use this is you want all your threads to share the same session and you want the session to always hold on to all the objects.</p>
<p><strong>Using Drools in a stateless, thread-safe manner</strong></p>
<p>The context I&#8217;ve needed to use Drools at Mersoft has been a thread-safe, stateless manner. In other words, each thread should have no knowledge of the objects or the rules the other threads are executing. I attempted to use this using the Stateless Session from the Knowledge Base, however, I had problems getting this to run in a stateless manner and I discovered that the Drools framework tends to have more bugs in the stateless implementation than in the stateful implementation. I have also discovered that in the stateless session, you cannot release the objects unless the class using the stateless session is completely disposed of. You can call &#8220;dispose&#8221; on a stateful session once you&#8217;re finished with it.</p>
<p>To do the stateless, thread safe, I generate a new stateful session for each request and dispose of the session when I&#8217;m through. Here&#8217;s an example:</p>
<pre>        package com.sample;

        import java.math.BigDecimal;

        import org.drools.KnowledgeBase;
        import org.drools.runtime.StatefulKnowledgeSession;
        import org.springframework.context.support.ClassPathXmlApplicationContext;

        import com.sample.model.SaleItem;
        import com.sample.model.SaleItem.State;
        import com.sample.model.SaleItem.Type;

        public class SalesTaxSpring {

            public static final void main(String[] args) {
                try {
                    // load up the knowledge base
                    final KnowledgeBase kbase = readKnowledgeBase();

                    Runnable shoppingCart1 = new Runnable() {

				public void run() {
                                    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
		                    //Non-prescription item
        		            //Expect $1.89 for the tax
	        	            SaleItem item1 = new SaleItem();
        		            item1.setPurchaseState(State.KANSAS);
	        	            item1.setItemType(Type.FOOD);
		                    item1.setSalesPrice(new BigDecimal(29.95));
		                    ksession.insert(item1);

		                    //Prescription item
        		            //Expect $0 for the tax
	        	            SaleItem item2 = new SaleItem();
		                    item2.setPurchaseState(State.KANSAS);
		                    item2.setItemType(Type.PRESCRIPTION_MEDICATION);
        		            item2.setSalesPrice(new BigDecimal(29.95));
	        	            ksession.insert(item2);

		                    //Non-prescription, non-food item
		                    //Expect $1.27 for the tax
        		            SaleItem item3 = new SaleItem();
	        	            item3.setPurchaseState(State.MISSOURI);
		                    item3.setItemType(Type.NON_FOOD_NON_MEDICATION_ITEM);
		                    item3.setSalesPrice(new BigDecimal(29.95));
        		            ksession.insert(item3);

	        	            //Prescription item
		                    //Expect $0 for the tax
		                    SaleItem item4 = new SaleItem();
        		            item4.setPurchaseState(State.MISSOURI);
	        	            item4.setItemType(Type.PRESCRIPTION_MEDICATION);
		                    item4.setSalesPrice(new BigDecimal(29.95));
		                    ksession.insert(item4);

        		            //Food item
	        	            //Expect $0.37 for the tax
		                    SaleItem item5 = new SaleItem();
		                    item5.setPurchaseState(State.MISSOURI);
        		            item5.setItemType(Type.FOOD);
	        	            item5.setSalesPrice(new BigDecimal(29.95));
		                    ksession.insert(item5);

		                    ksession.setGlobal("anotherHello", new AnotherHello());
				    ksession.startProcess("taxflow");
        		            ksession.fireAllRules();     

	        	            ksession.dispose();

				}
                    };

                    Runnable shoppingCart2 = new Runnable() {

				public void run() {
                                    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();

        		            SaleItem item = new SaleItem();
	        	            item.setPurchaseState(State.KANSAS);
		                    item.setItemType(Type.FOOD);
		                    item.setSalesPrice(new BigDecimal(32.45));
        		            ksession.insert(item);

	        	            item = new SaleItem();
		                    item.setPurchaseState(State.KANSAS);
		                    item.setItemType(Type.NON_FOOD_NON_MEDICATION_ITEM);
        		            item.setSalesPrice(new BigDecimal(255.05));
	        	            ksession.insert(item);

		                    item = new SaleItem();
		                    item.setPurchaseState(State.KANSAS);
        		            item.setItemType(Type.NON_PRESCRIPTION_MEDICATION);
	        	            item.setSalesPrice(new BigDecimal(14.70));
		                    ksession.insert(item);

		                    ksession.setGlobal("anotherHello", new AnotherHello());
				    ksession.startProcess("taxflow");
        		            ksession.fireAllRules();     

	        	            ksession.dispose();
				}
                      };

    		    Thread t1 = new Thread(shoppingCart1);
    		    Thread t2 = new Thread(shoppingCart2);
    		    Thread t3 = new Thread(shoppingCart2);

    		    t1.start();
    		    t2.start();
    		    t3.start();

                } catch (Throwable t) {
                    t.printStackTrace();
                }
            }

            private static KnowledgeBase readKnowledgeBase() throws Exception {
            	ClassPathXmlApplicationContext serviceContext = new ClassPathXmlApplicationContext( "droolsContext.xml" );
        	return (KnowledgeBase) serviceContext.getBean("kbase1");
            }

        }</pre>
<p>In this example, I&#8217;m using threading to demonstrate multiple threads running this process. I am calculating the shopping cart 2 twice.</p>
<p><strong>NOTE</strong>: If this is a system that runs the rules based on the events coming into the system, be sure to call the dispose. Without the dispose, the system will continue to use memory until it runs out of memory and starts throwing exceptions.</p>
<p>Here&#8217;s the output I received:</p>
<pre>        HELLO KANSAS!!!
        HELLO KANSAS!!!
        HELLO KANSAS!!!
        Total taxes: $19.04
        HELLO KANSAS!!!
        Hello KANSAS!!!!
        Total taxes: $3.52
        HELLO KANSAS!!!
        HELLO KANSAS!!!
        HELLO KANSAS!!!
        Total taxes: $19.04</pre>
<p>Although this isn&#8217;t an exhaustive list of what you can do with Drools, I feel it is enough to get someone started with using Drools. This is what I&#8217;ve picked up during my Drools quest and I hope this will be beneficial to someone else.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.mersoft.com%2F2011%2F09%2F07%2Fgetting-started-with-drools-5-2%2F&amp;linkname=Getting%20started%20with%20Drools%205.2"><img src="http://blog.mersoft.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://blog.mersoft.com/2011/09/07/getting-started-with-drools-5-2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>GWT-EXT 2.0.6 ComboBox &#8211; onChange event</title>
		<link>http://blog.mersoft.com/2010/05/25/gwt-ext-2-0-6-combobox-onchange-event/</link>
		<comments>http://blog.mersoft.com/2010/05/25/gwt-ext-2-0-6-combobox-onchange-event/#comments</comments>
		<pubDate>Tue, 25 May 2010 15:30:54 +0000</pubDate>
		<dc:creator>Tom Bollwitt</dc:creator>
				<category><![CDATA[Java/Java Frameworks]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[EXTJS]]></category>
		<category><![CDATA[google web toolkit]]></category>
		<category><![CDATA[Goolge Web Toolkit]]></category>
		<category><![CDATA[GWT]]></category>
		<category><![CDATA[GWT-EXT]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blog.mersoft.com/?p=363</guid>
		<description><![CDATA[I ran into an issue where I needed to use the onChange event for a Combobox and it was not working as expected. It only worked when the value was selected from the dropdown. This posed a problem for me since I was not forcing the user to make a selection &#8211; they can enter [...]]]></description>
			<content:encoded><![CDATA[<p>I ran into an issue where I needed to use the onChange event for a Combobox and it was not working as expected. It only worked when the value was selected from the dropdown. This posed a problem for me since I was not forcing the user to make a selection &#8211; they can enter in text manually.</p>
<p>I found <a href="http://www.extjs.com/forum/showthread.php?6343-Solved-1.0.1a-1.1-DateField-change-event-bugs-proposed-fixes&amp;p=52974#post52974" target="_blank">this fix</a> on the EXTJS forum, however the fix did not work when the user entered in their own value into the combo box.</p>
<p>To resolve this I changed 2 lines of code from the fix I found.</p>
<p>I modified&#8230;</p>
<pre>this.startValue = this.getValue();</pre>
<p>to</p>
<pre>this.startValue = this.getRawValue();</pre>
<p>and</p>
<pre>var v = this.getValue();</pre>
<p>to</p>
<pre>var v = this.getRawValue();</pre>
<p>So here is the entire code for the updated fix&#8230;</p>
<pre>Ext.override(Ext.form.Field, {
 onFocus : function() {
 if (!Ext.isOpera) { // don't touch in Opera
 this.el.addClass(this.focusClass);
 }
 if (!this.hasFocus) {
 this.hasFocus = true;
 <span style="color: #0000ff;"><strong>this.startValue = this.getRawValue();</strong></span>
 this.fireEvent("focus", this);
 }
 },

 onBlur : function() {
 this.beforeBlur();
 this.el.removeClass(this.focusClass);
 this.hasFocus = false;
 if (this.validationEvent !== false &amp;&amp; this.validateOnBlur &amp;&amp; this.validationEvent != "blur") {
 this.validate();
 }
 <span style="color: #0000ff;"><strong>var v = this.getRawValue();</strong></span>
 if (String(v) !== String(this.startValue)) {
 this.fireEvent('change', this, v, this.startValue);
 }
 this.fireEvent("blur", this);
 }
 });</pre>
<p>I hope this helps someone out there who may be having the same problem I had.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.mersoft.com%2F2010%2F05%2F25%2Fgwt-ext-2-0-6-combobox-onchange-event%2F&amp;linkname=GWT-EXT%202.0.6%20ComboBox%20%26%238211%3B%20onChange%20event"><img src="http://blog.mersoft.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://blog.mersoft.com/2010/05/25/gwt-ext-2-0-6-combobox-onchange-event/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WebSphere CE &#8211; Deploy WAR on its own port</title>
		<link>http://blog.mersoft.com/2010/01/15/websphere-ce-deploy-war-on-its-own-port/</link>
		<comments>http://blog.mersoft.com/2010/01/15/websphere-ce-deploy-war-on-its-own-port/#comments</comments>
		<pubDate>Fri, 15 Jan 2010 23:16:32 +0000</pubDate>
		<dc:creator>Tom Bollwitt</dc:creator>
				<category><![CDATA[Java/Java Frameworks]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[Geronimo]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[WAR]]></category>
		<category><![CDATA[WebSphere]]></category>
		<category><![CDATA[WebSphere CE]]></category>

		<guid isPermaLink="false">http://blog.mersoft.com/?p=354</guid>
		<description><![CDATA[I was tasked by the powers that be to figure out how to deploy a WAR in WebSphere Application Server Community Edition (WSASCE) under a separate port from other applications that were already running on our test server. After much googling and frustration, since I have never worked with WSASCE before, I finally figured it [...]]]></description>
			<content:encoded><![CDATA[<p>I was tasked by the powers that be to figure out how to deploy a WAR in WebSphere Application Server Community Edition (WSASCE) under a separate port from other applications that were already running on our test server. After much googling and frustration, since I have never worked with WSASCE before, I finally figured it out.</p>
<p>This ended up being fairly simple, however the the example from the <a title="WebSphere docs" href="http://publib.boulder.ibm.com/wasce/V2.0.0/en/configuring-resources-in-the-asset-scope.html#Configuringresourcesintheassetscope-ConfiguringaTomcatwebcontainer" target="_blank">WebSphere docs</a> did not work for me. I then was able to finally find some <a title="Geronimo docs" href="http://cwiki.apache.org/GMOxDOC22/app-per-port-running-multiple-web-apps-on-different-ports.html" target="_blank">Geronimo docs</a> that ended up working for me after a few minor adjustments since the example was for deploying an EAR.</p>
<p>Essentially all that needs to be done is to instruct WSASCE to create a new web container to deploy your WAR to. This can all be done via the deployment plan for your WAR.</p>
<p>Here is a sample deployment plan. Please note that there are a few things you will need to tweak for your envirnoment, which are noted after the sample.</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1"&gt;
  &lt;environment&gt;
    &lt;moduleId&gt;
      &lt;groupId&gt;GROUP_ID&lt;/groupId&gt;
      &lt;artifactId&gt;ARTIFACT_ID&lt;/artifactId&gt;
      &lt;version&gt;VERSION&lt;/version&gt;
      &lt;type&gt;war&lt;/type&gt;
    &lt;/moduleId&gt;
    &lt;dependencies /&gt;
    &lt;hidden-classes /&gt;
    &lt;non-overridable-classes /&gt;
  &lt;/environment&gt;
  &lt;context-root&gt;/YOUR_CONTEXT&lt;/context-root&gt;
  &lt;web-container&gt;
    &lt;gbean-link&gt;TomcatWebContainer1&lt;/gbean-link&gt;
  &lt;/web-container&gt;

  &lt;gbean name="TomcatWebConnector1"&gt;
    &lt;attribute name="name"&gt;HTTP&lt;/attribute&gt;
    &lt;attribute name="host"&gt;0.0.0.0&lt;/attribute&gt;
    &lt;attribute name="port"&gt;8090&lt;/attribute&gt;
    &lt;attribute name="maxHttpHeaderSize"&gt;8192&lt;/attribute&gt;
    &lt;attribute name="maxThreads"&gt;150&lt;/attribute&gt;
    &lt;attribute name="minSpareThreads"&gt;25&lt;/attribute&gt;
    &lt;attribute name="maxSpareThreads"&gt;75&lt;/attribute&gt;
    &lt;attribute name="enableLookups"&gt;false&lt;/attribute&gt;
    &lt;attribute name="redirectPort"&gt;8453&lt;/attribute&gt;
    &lt;attribute name="acceptCount"&gt;100&lt;/attribute&gt;
    &lt;attribute name="connectionTimeout"&gt;20000&lt;/attribute&gt;
    &lt;attribute name="disableUploadTimeout"&gt;true&lt;/attribute&gt;
    &lt;reference name="TomcatContainer"&gt;
      &lt;name&gt;TomcatWebContainer1&lt;/name&gt;
    &lt;/reference&gt;
    &lt;reference name="ServerInfo"&gt;
      &lt;name&gt;ServerInfo&lt;/name&gt;
    &lt;/reference&gt;
  &lt;/gbean&gt;

  &lt;gbean name="TomcatWebContainer1"&gt;
    &lt;attribute name="catalinaHome"&gt;var/catalina&lt;/attribute&gt;
    &lt;reference name="EngineGBean"&gt;
      &lt;name&gt;TomcatEngine1&lt;/name&gt;
    &lt;/reference&gt;
    &lt;reference name="ServerInfo"&gt;
      &lt;name&gt;ServerInfo&lt;/name&gt;
    &lt;/reference&gt;
    &lt;reference name="WebManager"&gt;
      &lt;name&gt;TomcatWebManager&lt;/name&gt;
    &lt;/reference&gt;
  &lt;/gbean&gt;

  &lt;gbean name="TomcatEngine1"&gt;
    &lt;attribute name="className"&gt;org.apache.geronimo.tomcat.TomcatEngine&lt;/attribute&gt;
    &lt;attribute name="initParams"&gt;
      name=Geronimo1
    &lt;/attribute&gt;
    &lt;reference name="DefaultHost"&gt;
      &lt;name&gt;TomcatHost1&lt;/name&gt;
    &lt;/reference&gt;
    &lt;references name="Hosts"&gt;
      &lt;pattern&gt;
        &lt;name&gt;TomcatHost1&lt;/name&gt;
      &lt;/pattern&gt;
    &lt;/references&gt;
    &lt;reference name="RealmGBean"&gt;
      &lt;name&gt;NoSecurityRealm&lt;/name&gt;
    &lt;/reference&gt;
  &lt;/gbean&gt;

  &lt;gbean name="TomcatHost1"&gt;
    &lt;attribute name="className"&gt;org.apache.catalina.core.StandardHost&lt;/attribute&gt;
    &lt;attribute name="initParams"&gt;
      name=localhost1
      appBase=
      workDir=work1
    &lt;/attribute&gt;
  &lt;/gbean&gt;

  &lt;gbean name="NoSecurityRealm"&gt;
    &lt;attribute name="className"&gt;org.apache.geronimo.tomcat.realm.TomcatEJBWSGeronimoRealm&lt;/attribute&gt;
  &lt;/gbean&gt;
&lt;/web-app&gt;</pre>
<p>You will need to replace the following placeholders in the above XML with values for your own WAR.</p>
<ul>
<li>GROUP_ID &#8211; Your group ID</li>
<li>ARTIFACT_ID &#8211; Your artifact ID</li>
<li>VERSION &#8211; The version of your WAR</li>
<li>YOUR_CONTEXT &#8211; The root context for your WAR</li>
</ul>
<p>You may also modify the following for your own environment if desired</p>
<ul>
<li><strong><em>TomcatWebContainer1</em></strong> is the name of the new web container.</li>
<li><em><strong>TomcatEngine1</strong></em> is the name of the new engine for the new web container.</li>
<li><em><strong>TomcatHost1</strong></em> is the name of the new virtual host in the new web container.</li>
<li><strong><em>TomcatWebManager</em></strong> is the name of the web manager of the new web container.</li>
<li><strong><em>TomcatWebManager</em></strong> is the name of the web manager defined in the initial server.</li>
<li><strong><em>TomcatJAASRealm</em></strong> is the name of the Tomcat realm for authenticating and authorizing users.</li>
<li><strong><em>TomcatJAASRealm</em></strong> is the name of the realm defined in the initial server configuration.</li>
<li><strong><em>0.0.0.0</em></strong> is replaced with the host name or IP address of the web containers host. The value localhost will restrict access to requesters in the server&#8217;s host. Use the value 0.0.0.0 if you  don&#8217;t want to provide the specific IP Address or host name.</li>
<li><strong><em>8090</em></strong> is replaced with the port number where the HTTP connector will listen for requests.</li>
</ul>
<p>To deploy your WAR into the new web container, include the <strong>&lt;web-container&gt;</strong> element and specify a <strong>&lt;gbean-link&gt;</strong> to the new container where <strong><em>TomcatWebContainer1</em></strong> is replaced with the name of the container GBean.</p>
<pre>
<pre> ...
 &lt;web-container&gt;
   &lt;gbean-link&gt;TomcatWebContainer1&lt;/gbean-link&gt;
 &lt;/web-container&gt;
 ...</pre>
</pre>
<p>Now just deploy your WAR with your new handy-dandy deployment plan.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.mersoft.com%2F2010%2F01%2F15%2Fwebsphere-ce-deploy-war-on-its-own-port%2F&amp;linkname=WebSphere%20CE%20%26%238211%3B%20Deploy%20WAR%20on%20its%20own%20port"><img src="http://blog.mersoft.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://blog.mersoft.com/2010/01/15/websphere-ce-deploy-war-on-its-own-port/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mac &#8211; Eclipse Galileo &#8211; Installing GWT Plugin</title>
		<link>http://blog.mersoft.com/2010/01/15/mac-eclipse-galileo-installing-gwt-plugin/</link>
		<comments>http://blog.mersoft.com/2010/01/15/mac-eclipse-galileo-installing-gwt-plugin/#comments</comments>
		<pubDate>Fri, 15 Jan 2010 22:26:39 +0000</pubDate>
		<dc:creator>Tom Bollwitt</dc:creator>
				<category><![CDATA[Java/Java Frameworks]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Goolge Web Toolkit]]></category>
		<category><![CDATA[GWT]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Plugin]]></category>

		<guid isPermaLink="false">http://blog.mersoft.com/?p=350</guid>
		<description><![CDATA[Ok, So I was having some real issues when I tried to install the GWT plugin from Google into Eclipse Galileo on my Mac in order create a GWT 2.0 application. After installing the plugin (via the update site &#8211; http://dl.google.com/eclipse/plugin/3.5) you need to restart Eclipse. However when Eclipse restarted all I got was an [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, So I was having some real issues when I tried to install the GWT plugin from Google into Eclipse Galileo on my Mac in order create a GWT 2.0 application. After installing the plugin (via the update site &#8211; http://dl.google.com/eclipse/plugin/3.5) you need to restart Eclipse. However when Eclipse restarted all I got was an error popup telling me to check the Eclipse log file.</p>
<p>The log file contained the following &#8230;</p>
<pre>!SESSION Thu Jan 14 16:42:24 CST 2010
------------------------------------------
!ENTRY org.eclipse.equinox.launcher 4 0 2010-01-14 16:42:24.080
!MESSAGE Exception launching the Eclipse Platform:
!STACK
java.lang.ClassNotFoundException:
org.eclipse.core.runtime.adaptor.EclipseStarter
	at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:316)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:556)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:514)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1311)</pre>
<p>Well, luckily I was able to come up with a workaround.</p>
<p>For development I also use the Subversive and Maven Integration plugins so here is what I did. (This assumes you know how to install plugins via update sites)</p>
<ol>
<li>Start with a fresh copy of Galileo</li>
<li>Add all the plugins without restarting Eclipse in the following order.</li>
<li>Add the GWT plugin from the update site
<ol>
<li>http://dl.google.com/eclipse/plugin/3.5</li>
</ol>
</li>
<li>Add the Subversive plugin and required SVN connectors from Polarion
<ol>
<li>http://community.polarion.com/projects/subversive/download/eclipse/2.0/galileo-site/</li>
</ol>
</li>
<li>Add the maven integration plugin
<ol>
<li>http://m2eclipse.sonatype.org/update</li>
</ol>
</li>
<li>After all the plugins are installed restart Eclipse.</li>
</ol>
<p>And there you have it. Eclipse starts up without any problems.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.mersoft.com%2F2010%2F01%2F15%2Fmac-eclipse-galileo-installing-gwt-plugin%2F&amp;linkname=Mac%20%26%238211%3B%20Eclipse%20Galileo%20%26%238211%3B%20Installing%20GWT%20Plugin"><img src="http://blog.mersoft.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://blog.mersoft.com/2010/01/15/mac-eclipse-galileo-installing-gwt-plugin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Open Office: invisible page break</title>
		<link>http://blog.mersoft.com/2009/12/03/open-office-invisible-page-break/</link>
		<comments>http://blog.mersoft.com/2009/12/03/open-office-invisible-page-break/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 22:42:07 +0000</pubDate>
		<dc:creator>Mandi Zinn</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Open Office]]></category>
		<category><![CDATA[page break]]></category>

		<guid isPermaLink="false">http://blog.mersoft.com/?p=346</guid>
		<description><![CDATA[When working on an open office document, I periodically come across an invisible page break (there&#8217;s no blue bar above the new page and I can&#8217;t seem to get rid of it easily). 
This always happens to me when I am using Open Office&#8217;s numbering to outline requirements. The page break is very annoying. When [...]]]></description>
			<content:encoded><![CDATA[<p>When working on an open office document, I periodically come across an invisible page break (there&#8217;s no blue bar above the new page and I can&#8217;t seem to get rid of it easily). </p>
<p>This always happens to me when I am using Open Office&#8217;s numbering to outline requirements. The page break is very annoying. When you try to remove it, it&#8217;ll pull one line of text up even with the line on the previous page. You can add a carriage return to separate the two lines, but you have to reformat the second line.</p>
<p>To get rid of this annoying space, you can start adding carriage returns where the space begins and keep adding them until you have started a new page. Then, you can highlight all the added carriage returns and hit the delete key and it gets rid of the invisible page break.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.mersoft.com%2F2009%2F12%2F03%2Fopen-office-invisible-page-break%2F&amp;linkname=Open%20Office%3A%20invisible%20page%20break"><img src="http://blog.mersoft.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://blog.mersoft.com/2009/12/03/open-office-invisible-page-break/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PowerBuilder 11 &#8220;Invalid character value for cast specification&#8221;</title>
		<link>http://blog.mersoft.com/2009/12/03/powerbuilder-11-invalid-character-value-for-cast-specification/</link>
		<comments>http://blog.mersoft.com/2009/12/03/powerbuilder-11-invalid-character-value-for-cast-specification/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 22:26:23 +0000</pubDate>
		<dc:creator>Mandi Zinn</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[invalid character]]></category>
		<category><![CDATA[Microsoft SQL Server 2000]]></category>
		<category><![CDATA[odbc]]></category>
		<category><![CDATA[powerbuilder]]></category>
		<category><![CDATA[SNC]]></category>

		<guid isPermaLink="false">http://blog.mersoft.com/?p=335</guid>
		<description><![CDATA[I was given the task of migrating a set of powerbuilder applications from version 8 to 11.5.
The PowerBuilder applications required a database connection. I went through their connection utility and the only connection type that I could get to work with my Microsoft SQL Server 2000 was ODBC. I configured it and PowerBuilder told me [...]]]></description>
			<content:encoded><![CDATA[<p>I was given the task of migrating a set of powerbuilder applications from version 8 to 11.5.</p>
<p>The PowerBuilder applications required a database connection. I went through their connection utility and the only connection type that I could get to work with my Microsoft SQL Server 2000 was ODBC. I configured it and PowerBuilder told me that it was working properly. I configured all of the applications to use the ODBC.</p>
<p>All of the applications worked properly, except one: the only application that uses stored procedures. The stored procedures that were failing had input and output parameters. They kept giving me the error message of</p>
<pre>
     [Microsoft][ODBC SQL Server Driver] Invalid character value for cast specification
</pre>
<p>I figured the problem was just a configuration issue. After extensive research, I found one forum that had a solution: adding </p>
<pre>
      StripParmNames='Yes',CallEscape='No'
</pre>
<p>to the end of the DBParm. I tried this. It fixed the &#8220;Invalid character&#8221; problem, but then I started getting the following error message:</p>
<pre>
     [Microsoft][ODBC SQL Server Driver] Incorrect syntax near 'OUTPUT'
</pre>
<p>Since everything seems to change when you tweak parameters, I tried every combination of parameters that I could see as possibly making a difference (both on the ODBC connection configuration and the DBParm settings).</p>
<p>Finally, I looked back at the original configuration and noticed that the DBMS was &#8220;MSS (Msoft) SQL Server 2000&#8243;. I started researching PowerBuilder database connection options and found this blog:</p>
<p><a href="http://sureshmoorthy.blogspot.com/2008/05/migrating-to-powerbuilder-11.html?showComment=1239682860000#c3657249529659890174">http://sureshmoorthy.blogspot.com/2008/05/migrating-to-powerbuilder-11.html?showComment=1239682860000#c3657249529659890174</a></p>
<p>Mainly, that PowerBuilder&#8217;s native driver (MSS) had been removed from PowerBuilder version 10 and that PowerBuilder 11 replaced it with SNC to support SQL Server 2000 &amp; 2005. Finally, I had found my solution. I switched my configuration to use the SNC driver and it solved all the problems I was having. Here&#8217;s the new configuration:</p>
<pre>
  DBMS=SNC
  Database=&lt;database name&gt;
  ServerName=&lt;server IP address&gt;
  LogId=&lt;db user name&gt;
  LogPassword=&lt;db password&gt;
  Lock=RU
  DbParm=staticbind=0,Async=1,AppName='&lt;app name&gt;'
</pre>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.mersoft.com%2F2009%2F12%2F03%2Fpowerbuilder-11-invalid-character-value-for-cast-specification%2F&amp;linkname=PowerBuilder%2011%20%26%238220%3BInvalid%20character%20value%20for%20cast%20specification%26%238221%3B"><img src="http://blog.mersoft.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://blog.mersoft.com/2009/12/03/powerbuilder-11-invalid-character-value-for-cast-specification/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Struts2 Rest Webservice</title>
		<link>http://blog.mersoft.com/2009/09/08/struts2-rest-webservice/</link>
		<comments>http://blog.mersoft.com/2009/09/08/struts2-rest-webservice/#comments</comments>
		<pubDate>Tue, 08 Sep 2009 14:10:52 +0000</pubDate>
		<dc:creator>Mandi Zinn</dc:creator>
				<category><![CDATA[Java/Java Frameworks]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[rest web service]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[struts 2]]></category>
		<category><![CDATA[struts 2 rest plugin]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[xml parser]]></category>

		<guid isPermaLink="false">http://blog.mersoft.com/?p=242</guid>
		<description><![CDATA[I started out trying to create a rest webservice for a project I&#8217;m working on with Mersoft. After a little bit of research, I discovered Apache has a rest plugin that enables Struts 2 to perform as a rest webservice.
I followed the documentation at http://struts.apache.org/2.x/docs/rest-plugin.html and created my rest webservice. However, I came across a [...]]]></description>
			<content:encoded><![CDATA[<p>I started out trying to create a rest webservice for a project I&#8217;m working on with <a title="Mersoft Corporation" href="http://www.mersoft.com">Mersoft</a>. After a little bit of research, I discovered Apache has a rest plugin that enables Struts 2 to perform as a rest webservice.</p>
<p>I followed the documentation at http://struts.apache.org/2.x/docs/rest-plugin.html and created my rest webservice. However, I came across a couple of issues that I could not find any documentation as to how to address. The first of these issues is that the documentation says that the rest plugin supports xml, json, and xhtml. I downloaded the rest example&#8217;s source jar and tore it apart, but there was nothing to address the xhtml. Next I installed the pre-compiled war and to my amazement, the xhtml worked. After I tore apart the war, I discovered what is required for the xhtml (I have that documented <a href="#xhtml">here</a>)</p>
<p>The second issue I came across was that I didn&#8217;t like how the xml was being displayed (instead of using just the object name as the xml tag, it included the package name). How to customize the xml display is documented <a href="#xml">here</a>.</p>
<p>The last struggle I had was that I wanted to use Spring to inject classes into my controllers. I searched online and found other developers asking how to do this, but could find nothing on how to actually do this. How to use Spring for the controllers is documented <a href="#spring">here</a>.</p>
<p>I am writing this blog to document what I did to create a rest webservice and to share what I did to resolve the issues I had.</p>
<p><strong>Creating a Rest Webservice</strong></p>
<p>To create a rest webservice, Apache created a rest plugin that works with Struts 2. This plugin was written with the intent of being used with the struts 2 convention plugin.</p>
<p>These are the only dependencies needing to be added to a Struts2 project:</p>
<pre>&lt;dependency&gt;
   &lt;groupId&gt;org.apache.struts&lt;/groupId&gt;
   &lt;artifactId&gt;struts2-rest-plugin&lt;/artifactId&gt;
   &lt;version&gt;${struts.version}&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
   &lt;groupId&gt;org.apache.struts&lt;/groupId&gt;
   &lt;artifactId&gt;struts2-convention-plugin&lt;/artifactId&gt;
   &lt;version&gt;${struts.version}&lt;/version&gt;
&lt;/dependency&gt;</pre>
<p>The web.xml must use the StrutsPrepareAndExecuteFilter for the struts 2 convention plugin (this Filter can also be used with other struts 2 applications as long as the application doesn&#8217;t need another filter that has to access the action&#8217;s context information). The web.xml should look like the following:</p>
<pre>&lt;web-app id="WebApp_9" version="2.4"
   xmlns="http://java.sun.com/xml/ns/j2ee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"&gt;

   &lt;filter&gt;
      &lt;filter-name&gt;action2&lt;/filter-name&gt;
      &lt;filter-class&gt;org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter&lt;/filter-class&gt;
   &lt;/filter&gt;

   &lt;filter-mapping&gt;
      &lt;filter-name&gt;action2&lt;/filter-name&gt;
      &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
   &lt;/filter-mapping&gt;

&lt;/web-app&gt;</pre>
<p>With the convention plugin, the only thing required in struts.xml is any changes in configuration needed for the convention plugin. If the web service is written without the convention plugin, you would just have to define each controller in the struts.xml (the same way an action is defined). The convention plugin just makes this defining process unnecessary.</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd"&gt;

&lt;struts&gt;

   &lt;!-- The struts rest plugin allows you to define the paths used for the webservice.
   If you have groupings of controllers and you want users to access the controllers based on the groupings, you can do this in the following way:
      1. create a package for each grouping (i.e. com.mersoft.test.group1, com.mersoft.test.group2)
      2. set the struts.convention.package.locators as the last package name before the groupings (i.e. "test")
      3. access the rest webservice by {application base}/{group name}/{controller name} (i.e. {application base}/group1/controller1, {application base}/group2/controller2)
   If you want all controllers accessed from the application base:
      1. put all the controllers in the same package (i.e. com.mersoft.controller).
      2. set the struts.convention.package.locators as the last package name (i.e. "controller")
     3. access the rest webservice by {application base}/{controller name} (i.e.  {application base}/controller1)
   --&gt;
   &lt;constant name="struts.convention.package.locators" value="[PACKAGE TO LOOK FOR CONTROLLERS]"/&gt;  &lt;!-- The convention plugin defaults this to "action,actions,struts,struts2" --&gt;
   &lt;constant name="struts.convention.action.suffix" value="Controller"/&gt;  &lt;!-- The convention plugin defaults this to "Action" --&gt;
   &lt;constant name="struts.convention.action.mapAllMatches" value="true"/&gt;   &lt;!-- The convention plugin defaults this to "false" --&gt;
   &lt;constant name="struts.convention.default.parent.package" value="rest-default"/&gt;  &lt;!-- The convention plugin defaults this to "convention-default". The "rest-default" is defined by the struts2 rest plugin --&gt;
&lt;/struts&gt;</pre>
<p>The objects being passed through the rest webservice need to be defined. These are just POJOs. Here&#8217;s an example:</p>
<pre>package com.mersoft.web.model;

public class TestObject {

   private String id;
   private String someString;
   private long someLong;
   private String anotherString;

   public String getId() {
      return id;
   }
   public void setId(String id) {
      this.id = id;
   }
   public String getSomeString() {
      return someString;
   }
   public void setSomeString(String someString) {
      this.someString = someString;
   }
   public long getSomeLong() {
      return someLong;
   }
   public void setSomeLong(long someLong) {
      this.someLong = someLong;
   }
   public String getAnotherString() {
      return anotherString;
   }
   public void setAnotherString(String anotherString) {
      this.anotherString = anotherString;
   }
}</pre>
<p>The rest webservice uses &#8220;controllers&#8221; for data manipulation. The controllers must implement ModelDriven&lt;T&gt;. In my example below I added the Validateable interface and the ValidationAwareSupport extension. This allows the controller to be validated prior to any executions.</p>
<p><strong>NOTE:</strong> The Controller name must not use camel casing. (i.e. use TestinstanceController instead of TestInstanceController).</p>
<pre>package com.mersoft.web.controller;

import org.apache.struts2.rest.DefaultHttpHeaders;
import org.apache.struts2.rest.HttpHeaders;

import com.mersoft.web.model.TestObject;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Validateable;
import com.opensymphony.xwork2.ValidationAwareSupport;

public class TestController extends ValidationAwareSupport implements ModelDriven&lt;TestObject&gt;, Validateable{
   /**
   *
   */
   private static final long serialVersionUID = -1045170916847707617L;

   private TestObject testObject = new TestObject();

   private String id;

   public TestController() {
      super();
   }

   public TestObject getModel() {
      //TODO: populate test object
      return testObject;
   }

   // GET /test/1
   public HttpHeaders show() {
      return new DefaultHttpHeaders("show");
   }

   // GET /test
   public HttpHeaders index() {
      return new DefaultHttpHeaders("index");
   }

   // POST /test
   public HttpHeaders create() throws Exception {
      //TODO: creation action here

      return new DefaultHttpHeaders("success");
   }

   //PUT /test/1
   public String update() throws Exception {
      //TODO: update action here
      return "success";
   }

   // DELETE /test/1
   public String destroy() {
      //TODO: delete action here
      return "success";
   }

   public void validate() {
      // TODO add validation here

   }

   public String getId() {
      return id;
   }

   public void setId(String id) {
      this.id = id;
   }

}</pre>
<p>To access the webservice, you just need to make the request. (Look above at the type of request and the parameters that need to be passed to access each method.)</p>
<p>For xml requests, add .xml to the end of the url (i.e. Making a GET request to {application base}/test.xml will access the index method and return an xml response).<br />
For json requests, add .json to the end of the url (i.e. Making a GET request to {application base}/test.json will access the index method and return a json response).</p>
<p><strong>Adding custom methods</strong></p>
<p>The rest webservice plugin is designed to be flexible. If there&#8217;s actions you don&#8217;t want the user to be able to perform, you simply omit it from the controller. If there&#8217;s a special action that is not part of the standard actions, you just add the custom action to your controller:</p>
<pre>   public String test() {
      return "test";
   }</pre>
<p>To access the above action, make a GET request to {application base}/test/1/test.xml.</p>
<p><strong><a name="xhtml">Accessing the webservice via xhtml</a></strong></p>
<p>Out of the box, the rest webservice supports xhtml, however you must create the jsp pages the webservice must display to the user.</p>
<p>By default, the convention plugin expects these files in WEB-INF/content/ (this can be changed by adding &lt;constant name=&#8221;struts.convention.result.path&#8221; value=&#8221;/WEB-INF/{jsp directory}&#8221;/&gt; to struts.xml)   . The file names must be {controller name}-{request name}.jsp. For example, for the jsp corresponding to the show action in TestController, the file name should be test-show.jsp.</p>
<p><strong>NOTE:</strong> To display objects returned by the getModel() method, you just need to reference the object name within the model. (i.e. to display someString from the TestObject, you can reference it as ${someString} in the jsp)</p>
<p>For requests needing to be sent as a PUT or a DELETE, you can attach &#8220;?_method={REQUEST TYPE} to the end of the action method in the form and send the request as a post.</p>
<p><strong><a name="xml">Customizing xml response</a></strong></p>
<p>To make the xml cleaner, I wanted to display just the object name without the package the object is in. After doing a little bit of research, I discovered that the struts-rest plugin uses XStream. The latest version of XStream allows annotations to customize the xml. Since the struts-rest plugin doesn&#8217;t use the latest XStream, I created my own ContentTypeHandler using the latest XStream.</p>
<p>Be sure to add the XStream dependency to the classpath:</p>
<pre>&lt;dependency&gt;
   &lt;groupId&gt;com.thoughtworks.xstream&lt;/groupId&gt;
   &lt;artifactId&gt;xstream&lt;/artifactId&gt;
   &lt;version&gt;1.3.1&lt;/version&gt;
&lt;/dependency&gt;</pre>
<p>The ContentTypeHandler I created is very similar to that of the rest plugin&#8217;s XML content handler. The main difference is that I told XStream to process annotations.</p>
<p><strong>NOTE:</strong> This must implement org.apache.struts2.rest.handler.ContentTypeHandler to work with the struts rest plugin.</p>
<pre>package com.mersoft.rest.handler;

import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

import org.apache.struts2.rest.handler.ContentTypeHandler;

import com.thoughtworks.xstream.XStream;

/**
* Handles XML content
*/
public class XStreamHandler implements ContentTypeHandler {

   public String fromObject(Object obj, String resultCode, Writer out) throws IOException {
      if (obj != null) {
         XStream xstream = new XStream();
         xstream.processAnnotations(obj.getClass());
         xstream.toXML(obj, out);
      }
      return null;
   }

   public void toObject(Reader in, Object target) {
      XStream xstream = new XStream();
      xstream.processAnnotations(target.getClass());
      xstream.fromXML(in, target);
   }

   public String getContentType() {
      return "application/xml";
   }

   public String getExtension() {
      return "xml";
   }
}</pre>
<p>To use the new content handler, I had to add the following line to my struts.xml:</p>
<pre>   &lt;bean type="org.apache.struts2.rest.handler.ContentTypeHandler" name="myXml" class="com.mersoft.rest.handler.XStreamHandler" /&gt;</pre>
<p>To tell the rest plugin to use my new content handler, I simply have to add the bean name to a struts.properties file:</p>
<pre>struts.rest.handlerOverride.xml=myXml</pre>
<p>Now I can use the XStream annotations. Here&#8217;s an example of how to use the annotations with the TestObject:</p>
<pre>package com.mersoft.web.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamOmitField;

@XStreamAlias("test")
public class TestObject {

   private String id;
   private String someString;

   @XStreamOmitField
   private long someLong;

   private String anotherString;
   ...</pre>
<p>For more on XStream&#8217;s annotations see <a href="http://xstream.codehaus.org/annotations-tutorial.html">http://xstream.codehaus.org/annotations-tutorial.html</a></p>
<p><strong><a name="spring">Using Spring Dependency Injection on the Controllers</a></strong></p>
<p>With the rest webservice I was creating, I wanted to spring inject my managers into my controllers. After searching on the web, I couldn&#8217;t find any answers on how to do this. Analyzing what I have accomplished so far, I realized that the controllers were no more than specialized actions. My biggest obstacle was discovering how to use the struts2 spring plugin with the struts2 convention plugin. The struts2 spring plugin pulls the &#8220;class&#8221; name from the struts.xml file. If the &#8220;class&#8221; name matches a bean definition, then the spring plugin pulls the bean. If it does not match a bean definition, then it pulls the class. After discovering this, it was pretty clear as to how to get this to work with the struts convention plugin.</p>
<p>First, I added the struts2 spring plugin dependency:</p>
<pre>&lt;dependency&gt;
   &lt;groupId&gt;org.apache.struts&lt;/groupId&gt;
   &lt;artifactId&gt;struts2-spring-plugin&lt;/artifactId&gt;
   &lt;version&gt;${struts.version}&lt;/version&gt;
&lt;/dependency&gt;</pre>
<p>As the standard struts2 spring plugin requires, we must configure it in web.xml by setting up the context path and including the context listener:</p>
<pre>   &lt;context-param&gt;
      &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
      &lt;param-value&gt;
         classpath:/applicationContext-resources.xml
         classpath:/applicationContext-dao.xml
         classpath*:/applicationContext.xml
      &lt;/param-value&gt;
   &lt;/context-param&gt;

   &lt;listener&gt;
      &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
   &lt;/listener&gt;</pre>
<p>The only thing left was to set up the applicationContext.xml. In order for the spring plugin to pull the beans based on this configuration, the bean id must match the bean class.</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"&gt;

   &lt;bean id="com.mersoft.web.controller.TestController" &gt;
      &lt;constructor-arg ref="testManager" /&gt;
   &lt;/bean&gt;
&lt;/beans&gt;</pre>
<p><strong> </strong></p>
<p><strong>NOTE:</strong> This will call the TestController constructor with the constructor containing the &#8220;testManager&#8221; class (i.e.: public TestController(TestManager testManager))</p>
<p>For more information on the struts2 spring plugin, you can see <a href="http://struts.apache.org/2.0.8/docs/spring-plugin.html">http://struts.apache.org/2.0.8/docs/spring-plugin.html</a></p>
<p>With this last issue resolved, I was able to do everything I wanted to do with my rest webservice. I hope this is helpful.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.mersoft.com%2F2009%2F09%2F08%2Fstruts2-rest-webservice%2F&amp;linkname=Struts2%20Rest%20Webservice"><img src="http://blog.mersoft.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://blog.mersoft.com/2009/09/08/struts2-rest-webservice/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

