Redefining Web Applications with AJAX, Servlets and JSON

In this article I would like to show how JSON (JavaScript Object Notation) and Java servlet can be used together in a little AJAX (Asynchronous JavaScript and XML) application.

To give brief description to those who are not closely familiar with JSON -

JSON is a lightweight syntax for representing data, which makes working with it much more pleasant than with XML and makes AJAX applications faster. Also, when working with JSON, there is no need for an XML parsing.

In the following example, I am going to create a callback servlet that fetches and parses an RSS feed. Then the parsed feed data is passed to the client side in a form of JSON. The data then formatted and presented to the user. The client uses AJAX call to query the servlet.

For this application, I used three third-party libraries:

  1. JSON library provided by JSON.org and extended by JSON-RPC-Java which allows to create and easily parse JSON data through Java code. This library can run in a Servlet container such as Tomcat, JBoss and other J2EE Application servers.
  2. Project ROME
    ROME is an set of open source Java tools for parsing, generating and publishing RSS and Atom feeds.
  3. JDOM XML parser
    JDOM is a Java-based “document object model” for XML files. JDOM serves the same purpose as DOM, but is easier to use

The libraries are included in the source code which accompanies this article. This application example is also included as a WAR archive, ready to be deployed on Tomcat.

The following is my servlet implementation. The servlet fetches and parses feed data. The JSON library mentioned previously allows me easily to create and populate JSON object.

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import org.json.JSONObject;

import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.fetcher.FeedFetcher;
import com.sun.syndication.fetcher.FetcherException;
import com.sun.syndication.fetcher.impl.FeedFetcherCache;
import com.sun.syndication.fetcher.impl.HashMapFeedInfoCache;
import com.sun.syndication.fetcher.impl.HttpURLFeedFetcher;
import com.sun.syndication.io.FeedException;

/**
* @author Alexander Zagniotov (http://javabeans.asia)
*/
public class JsonServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	private static final String BLOG_URL = "http://javabeans.asia/rss.xml";
	private static final String CONTENT_TYPE = "application/json";
	private FeedFetcherCache feedInfoCache = null;
	private FeedFetcher feedFetcher = null;

	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		feedInfoCache = HashMapFeedInfoCache.getInstance();
		feedFetcher = new HttpURLFeedFetcher(feedInfoCache);
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		SyndFeed feed = this.feedFethcer(BLOG_URL);
		if (feed != null) {
			String json = this.feedToJSON(feed);
			response.setContentType(CONTENT_TYPE);
			response.setHeader("Cache-Control", "no-cache");
			response.getWriter().write(json);
		}
	}

	private SyndFeed feedFethcer(String url) {
		SyndFeed feed = null;
		try {
			feed = feedFetcher.retrieveFeed(new URL(BLOG_URL));
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (FeedException e) {
			e.printStackTrace();
		} catch (FetcherException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return feed;
	}

	private String feedToJSON(SyndFeed feed) {

		JSONObject jsonObj = new JSONObject();
		JSONArray jsonEntryTitles = new JSONArray();
		jsonObj.put("blogtitle", feed.getTitle());
		jsonObj.put("blogdescription", feed.getDescription());
		jsonObj.put("bloglanguage", feed.getLanguage());
		jsonObj.put("bloglink", feed.getLink());
		jsonObj.put("author", feed.getCopyright());

		List<?> feedEntries = feed.getEntries();

		for (Object c : feedEntries) {
			SyndEntry syndicateEntry = (SyndEntry) c;
			jsonEntryTitles.put(syndicateEntry.getTitle());
		}

		jsonObj.put("blogentrytitles", jsonEntryTitles);
		return jsonObj.toString();
	}
}

As you can see it is very easy to construct JSON objects and arrays on the server side and pass them to the client. For the purpose of this example I am getting my data from RSS feed, but the data can also be coming from DB etc.

The following is my client implementation. The client queries the servlet using AJAX call. When an AJAX call returns a response from the servlet in a form of JSON object, the object data is formatted and information about the RSS feed is presented to the client:

<html>
    <head>
    <title>Java Beans dot Asia</title>

    <script language="JavaScript" type="text/javascript">

        var httpRequest = null;

    function getDescriptionAsJSON() {
        var description = document.getElementById('description');
        description.innerHTML = "Loading, please wait ...";

        var url = "http://localhost:8080/json/json";
        if(window.XMLHttpRequest){
            httpRequest = new XMLHttpRequest();
        } else if(window.ActiveXObject){
            httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
        }

        httpRequest.open("GET", url, true);
        httpRequest.onreadystatechange = handler;
        httpRequest.send(null);
    }

    function handler() {
        if (httpRequest.readyState == 4) {
            if (httpRequest.status == 200) {
                processJSON(httpRequest.responseText);
            }
        }
    }

    function processJSON(jsonObjectString) {

        var description = document.getElementById('description');

        //Since JSON is a subset of JavaScript, I am using
        //JavaScript's own compiler to parse JSON in one line!

        var jsonObject = eval('(' + jsonObjectString + ')')
        var text = "";

        text += "Author: " + jsonObject.author + "< br />";
        text += "Blog Name: " + jsonObject.blogtitle + "< br />";
        text += "Blog URL: " +    jsonObject.bloglink + "< br />";
        text += "Blog Description: " +    jsonObject.blogdescription + "< br />";
        text += "Blog Language: " + jsonObject.bloglanguage + "< br />";

        description.innerHTML = text;
        var entries = "Last " + jsonObject.blogentrytitles.length + " blog entries are:nn";

        for (var index = 0; index < jsonObject.blogentrytitles.length; index ++) {
            entries += (index + 1) + ": " + jsonObject.blogentrytitles[index] + "n";
        }
        alert(entries);
    }

    </script>

    </head>
    <body>
        <img src="images/javabeansmugshot_120x120.jpg" border="1" />< br />< br />
        <div id="description"></div>< br />< br />
        <a href="javascript:void(0)" onclick="return getDescriptionAsJSON();">Click to get description!</a>
    </body>
</html>

As you could see, JSON data can be easily parsed on the client side with the help of Java script eval() function. To remind – JSON is a subset of Java script, therefore eval() will produce a valid object.

Keep in mind, that there is a need for extra care when using eval. The problem is that eval will compile and execute Java script code that coming back from the response. This could cause a security risk if the response data is coming from an untrusted source.

That’s it. I hope this example was clear and helpful :)

source json servlets ajax

Please note that this example was tested by me and its working fine. The source code as mentioned previously is included as Eclipse project. You can simply create a new Java project from the existing Ant build.xml file.

Comments/flames are appreciated :)

Cheers

You Gotta Love Linux

Last Friday as I was working, I was asked to get some information from the application logs for a particular period of time. I needed to extract some data and count the results. The given period was last twelve months.

Luckily I am working with Linux, so I opened a shell session and typed the following after doing some research on the Internet:

grep -B4 "String1" *.log | grep "String2" | cut -d   -f2 | sort -u | wc -l

Basically what the command does is:

  1. In all files with extension log , grab 4 lines before occurrence of “String1″ and pass the outcome result to the next command
  2. Find occurrence of “String2″ and pass the outcome result to the next command
  3. Split by SPACE delimiter and grab the second field and pass the outcome result to the next command
  4. Sort in unique manner and pass the outcome result to the next command
  5. Count the results and output

Simple and efficient. The whole process took only few seconds.

I do not think I could have done this so easily if I would be working on Win platform…

You gotta’ love Linux! ;)

Rule Engine Stress Testing

I came across a blog by a company called Illation. What those guys do is compare performance of several rule engines available on the market: Drools, ILog, OPSJ and Jess.

The stress tests cover different aspects, for example:

  • Rules firing time
  • Data load time
  • Memory usage
  • Pre-run memory used
  • Post-run memory used

The test results available on their blog for the wide public. The team also makes business rules, object model and datasets used in their stress tests available for download if someone wishes to repeat the tests. Some of the results look very interesting

VMware and Melbourne IT Launch Cloud Service

Australian web hosting provider from Melbourne, Melbourne IT has launched cloud computing services together with VMware. The service is still in beta mode and it is called “vCloud Express

Its nice to see local provider offering cloud computing services as other big players on the market. A lot of customers having second thoughts to trust giants like Amazon, Microsoft Azure or Google. Having local provider allows businesses and individuals to have more personal customer relationship with their cloud computing provider.

Read the full article about it.

Drools 5 Case Study 2 – Complex Event Processing

In my previous post Drools 5 – Complex Event Processing, I gave introduction to Drools Fusion module. In the current post, I would like to demonstrate Drools Fusion capabilities.

As an example chosen for the current article, I decided to use a scenario when an insurance firm rewards its policy members. The members are rewarded when they keep a low average of claimed money under the threshold set on their account over a period of time.

In other words, if the policy member had last five claims average and average of claims during last ninety (90) days lower than the threshold limit – he/she will be eligible for a reward.

Drools allows us to test for these conditions by applying the sliding window concept. So to obtain a claim average for a particular period in time, I will use time based sliding window. To obtain an average of last five claims, I will use length based sliding window.

Before I begin, I would like to say that the source code for this article is available as attachment, the download link is at the bottom.

Ok, lets begin. Below is my POJO Account:

public class Account {
	private String number = "";
	private double threshold = 0.00;

	public Account() {
		super();
	}

	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public double getThreshold() {
		return threshold;
	}

	public void setThreshold(double threshold) {
		this.threshold = threshold;
	}
}

The following is my implementation of the claim event POJO:

public class ClaimApprovedEvent implements Serializable {

	private static final long serialVersionUID = 1L;
	private String accountNumber = "";
	private double amount = 0.00;

	public ClaimApprovedEvent(String accountNumber, double amount) {
		this.accountNumber = accountNumber;
		this.amount = amount;
	}

	public String getAccountNumber() {
		return accountNumber;
	}

	public void setAccountNumber(String accountNumber) {
		this.accountNumber = accountNumber;
	}

	public double getAmount() {
		return amount;
	}

	public void setAmount(double amount) {
		this.amount = amount;
	}
}

This event represents a claim event when a policy member has claimed some money. Event contains policy member account number and the claim amount. These events, I will be “feeding” in to the KnowledgeSession as facts. Yes, they are play a role knowledge facts in Drools.

Having said that I want to point out that all events are facts, but not all facts are events. I know it maybe a little bit confusing, but if you read Drools 5.0 doco it will become more clearer to you.

To give some information about it – events almost never change state in Drools (almost means it is still possible to change the state of event), therefore they are immutable.

Events simply hold information about something that has already happened and because you cannot change what has already happened – events are immutable. Events also allow the use of sliding windows.

The following is implementation of a POJO, that plays a role of a common data structure for rules to use at run time. It is one of the new features that available in Drools 5. Keep in mind – that this is not a knowledge fact, but just a data structure.

This POJO is an internal type, therefore there is no need to create new instance of this class. The object will only be created at run time, when the knowledge package is compiled (In my tester class I show how to do it). For now, we just have to add POJOs declaration to DRL, and to have the source file present. Later on, you will see how the declaration in DRL is done:

public class AccountInfo {

	private String accountNumber = "";
	private double aveOfLastClaims = 0.00;
	private double aveForPeriod = 0.00;
	private boolean eligibleForBonusClaims = false;
	private boolean eligibleForPeriodicBonus = false;

	public AccountInfo() {
		super();
	}

	public String getAccountNumber() {
		return accountNumber;
	}

	public void setAccountNumber(String accountNumber) {
		this.accountNumber = accountNumber;
	}

	public double getAveOfLastClaims() {
		return aveOfLastClaims;
	}

	public void setAveOfLastClaims(double aveOfLastClaims) {
		this.aveOfLastClaims = aveOfLastClaims;
	}

	public double getAveForPeriod() {
		return aveForPeriod;
	}

	public void setAveForPeriod(double aveForPeriod) {
		this.aveForPeriod = aveForPeriod;
	}

	public boolean isEligibleForBonusClaims() {
		return eligibleForBonusClaims;
	}

	public void setEligibleForBonusClaims(oolean eligibleForBonusClaims) {
		this.eligibleForBonusClaims = eligibleForBonusClaims;
	}

	public boolean isEligibleForPeriodicBonus() {
		return eligibleForPeriodicBonus;
	}

	public void setEligibleForPeriodicBonus(boolean eligibleForPeriodicBonus) {
		this.eligibleForPeriodicBonus = eligibleForPeriodicBonus;
	}
}

…and the following is the DRL:

package net.javabeansdotasia.casestudy.pojo;

import net.javabeansdotasia.casestudy.pojo.ClaimApprovedEven
import net.javabeansdotasia.casestudy.pojo.Account;

declare ClaimApprovedEvent
	// declare a fact type as an event, default is 'fact'
	@role( event )
end

// Decalare common data structure for all rules to use
declare AccountInfo
	accountNumber : String
	aveOfLastClaims : Double
	aveForPeriod : Double
	eligibleForBonusClaims : Boolean
	eligibleForPeriodicBonus : Boolean
end

rule "FiveLastClaims"
	dialect "mvel"
	no-loop true
	salience 100

when
	$account : Account()

	//check if the average of last five claims is less
	//than the account threshold
	$aveOfLastClaims : Number($account.threshold > doubleValue )
		from accumulate(
			ClaimApprovedEvent(
				accountNumber == $account.number,
				$amount : amount
			)
			over window:length( 5 ) from entry-point ClaimStream,
			average($amount)
		)

	//the member must not have received eligibility
	//for last claim bonus yet
	$accountInfo : AccountInfo(accountNumber == $account.number, eligibleForBonusClaims == false )

then  modify($accountInfo) {
	setAveOfLastClaims($aveOfLastClaims);
	setEligibleForBonusClaims(true);
	};
end

rule "NinetyDaysPeriod"
	dialect "mvel"
	no-loop true
	salience 90

when
	$account : Account()

	//check if the average of claims for period is less
	//than the account threshold
	$aveForPeriod : Number($account.threshold > doubleValue )
		from accumulate(
			ClaimApprovedEvent(
				accountNumber == $account.number,
				$amount : amount
			)
			over window:time( 90d ) from entry-point ClaimStream,
			average($amount))

	//the member must have eligibility for last claim bonus and
	//the member must not have received eligibility for
	//periodic bonus yet
	$accountInfo : AccountInfo(accountNumber == $account.number, eligibleForBonusClaims == true, eligibleForPeriodicBonus == false)

then  modify($accountInfo) {
	setAveForPeriod($aveForPeriod);
	setEligibleForPeriodicBonus(true);
	};
end

rule "EligibleForVoucher"
	dialect "mvel"
	no-loop true
	salience 80

when
	$account : Account()

	//the member must have eligibility for last claim bonus and
	//the member must have eligibility for periodic bonus
	$accountInfo : AccountInfo(
		accountNumber == $account.number, eligibleForBonusClaims == true, eligibleForPeriodicBonus == true)
then
	System.out.println("Notifying policy member...");
	System.out.println("Dear member, you have claimed "  + "in average $" +
			$accountInfo.aveOfLastClaims +   " during last five claims, which is " +
			"under the account threshold of $" + $account.threshold);

	System.out.println("Dear member, you have claimed " +  "in average $" +
			$accountInfo.aveForPeriod +   " during last 90 days, which is "+
			"under the account threshold of $" + $account.threshold);

	System.out.println("You are eligible for a holiday!");
end

Lets have a look what does this DRL do:

1. Modifying existing type by specifying that ClaimApprovedEvent is an event (line 6). To allow Drools to process events, we have to set that the fact is of type event
2. Declaring new type that plays the role of a common data structure (line 12). This is the declaration that I was talking about previously.
3. rule “FiveLastClaims” obtains an average of last five event claims and compares it to the account threshold. If the rule return true, the AccountInfo is updated with new data for other rules to use.
4. rule “NinetyDaysPeriod” obtains an average claim totals over a period of ninety (90) days and compares it to the account threshold. If the rule return true, the AccountInfo is updated with new data for other rules to use
5. rule “EligibleForVoucher” checks if the account owner has both eligibility for a periodic bonus and last five claim bonus, if true – the policy member will be eligible for a reward

The following is the snippet code from my Tester class where I show how to I load claim events over a period of time into the Knowledge session entry point (once again to remind: please refer to the source code attached for more information):

SessionPseudoClock clock = session.getSessionClock();
WorkingMemoryEntryPoint claimStream = session.getWorkingMemoryEntryPoint("ClaimStream");
claimStream.insert(new ClaimApprovedEvent(account.getNumber(), 12.00));
clock.advanceTime(80, TimeUnit.DAYS);
claimStream.insert(new ClaimApprovedEvent(account.getNumber(), 46.00));
clock.advanceTime(15, TimeUnit.DAYS);
claimStream.insert(new ClaimApprovedEvent(account.getNumber(), 60.00));
clock.advanceTime(45, TimeUnit.DAYS);
claimStream.insert(new ClaimApprovedEvent(account.getNumber(), 110.00));
clock.advanceTime(60, TimeUnit.DAYS);
claimStream.insert(new ClaimApprovedEvent(account.getNumber(), 20.00));
session.insert(account);
session.insert(accountInfo);
session.fireAllRules();

Please note an entry point “ClaimStream”. Entry point plays a role of a partition in KnowledgeSession in Drools. Partitioning is also a new concept in Drools that makes KnowledgeSession multithreaded. You can have multiple entry points and choose where to insert the fact.

In the current example, I use only one partition (or entry point). If I would to use more than one, than I would have to enable multi-partitioning with the following code:

KnowledgeBaseConfiguration config = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
config.setOption(MultithreadEvaluationOption.YES);

Have a read Drools Fusion manual, the team really gives a good cover of this concept.

I use SessionPseudoClock that allows me to test the rules by feeding claim events into the KnowledgeSession over a period of time. As you can see, after each event I move the clock forward, simulation submission of each claim event in different time.

The following is the program output:

Notifying policy member...
Dear member, you have claimed in average $49.6 during last five claims, which is under the account threshold of $70.0
Dear member, you have claimed in average $65.0 during last 90 days, which is under the account threshold of $70.0
You are eligible for a holiday!

That’s it. In this example I showed how it is possible to process complex events over a period of time by applying sliding window concept.

Please note that the above example was tested by me and its working fine. I also included source files for the above example as Eclipse project. You can simply create a new Java project from this existing Ant build.xml file.

Also, I wanted to point out that in my Eclipse project setup my Drools binaries located under JAVA_HOME/lib/drools-5.0-bin/ (have a look at the build.xml)

I hope this was clear :)

Cheers

drools-case-study-2-CEP

Resources:

Drools JBoss Rules 5.0 Developer’s Guide July 2009

Drools 5 – Complex Event Processing

From Drools version 4 to version 5, the framework has undergone quite a few improvements. These include support for three additional business modeling techniques. So today, Drools is not only a rule engine, but much more than that.

One of these techniques is event processing. The module that added event processing capabilities to the framework is called Drools Fusion. It supports Complex Event Processing (CEP) and Event Stream Processing (ESP).

“…Complex Event Processing, or CEP, is primarily an event processing concept that deals with the task of processing multiple events with the goal of identifying the meaningful events within the event cloud. CEP employs techniques such as detection of complex patterns of many events, event correlation and abstraction, event hierarchies, and relationships between events such as causality, membership, and timing, and event-driven processes…”

http://en.wikipedia.org/wiki/Complex_Event_Processing

Drools Fusion utilizes event processing architecture that adds loose coupling to its components. In other words, one party can publish events and other party can listen to those events while unaware of the publishing party.

Event can represent a change in state, for example banking transaction or insurance claim that was processed. CEP deals with complex event processing. Complex event is a collection of simpler events. Please refer to the diagram below:

Drools - complex event processing

In my next post Drools 5 Case Study 2 – Complex Event Processing, I talk about CEP and how Drools applies its processing power to solve complex event problems.

Drools 5 Case Study 1- Writing DSL for DRL rule

One of the blog readers, who posted a comment in my previous post Drools – tutorial on writing DSL template asked to me to help him with creating DSL for the following rule, so I decided to use his example as a small case study:

For readability, I added some comments to the original rule:

rule 'Rank accomodation name'
salience 90
when
     //Matches every AccomodationBase
     $accBase: AccomodationBase()

     //Uses inline eval to evaluate that there is
     //no AccomodationBase of type AccomodationRank
     //in the session.

     //To remind: inline eval evaluated only once
     //and then it is cached by Drools.

     not AccomodationBase(eval($accBase
                       instanceof AccomodationRank))

     //Matches every AccomodationRank that has the same
     //level and the description as the AccomodationBase
     $accRank: AccomodationRank(
            level == $accBase.level,
	    description == $accBase.description)
then
     //Increments the score
     $accRank.setScore($accRank.getScore()+1);
end

For my solution, I created two POJOs, tester class DSL and DSLR files. The following is my DSL:

[when]AccomodationBaseObj = $accBase: AccomodationBase()
[when]There is Accomodation base object of type Accomodation rank = eval($accBase instanceof AccomodationRank)
[when]AccomodationRankObj = $accRank: AccomodationRank(level == $accBase.level, description == $accBase.description)
[then]IncrementScore = $accRank.setScore($accRank.score+1);
[then]PrintScore = System.out.println("Rank score: " + $accRank.score);
[then]PrintLevel = System.out.println("Base level: " + $accBase.level);

and this is the DSLR file:

package net.javabeansdotasia.casestudy;

expander accomodation.dsl

import net.javabeansdotasia.casestudy.pojo.AccomodationBase;
import net.javabeansdotasia.casestudy.pojo.AccomodationRank;

rule "Rank"
dialect "mvel"
when
   AccomodationBaseObj
   not (There is Accomodation base object of type Accomodation rank)
   AccomodationRankObj
then
   IncrementScore
   PrintScore
   PrintLevel
end

In the following class I load DSL and DSLR files in to the KnowledgeBuilder and get a KnowledgeBase object. Once I have the KnowledgeBase object, I can get StatefulKnowledgeSession or StatelessKnowledgeSession, depends on what I want to do.

package net.javabeansdotasia.casestudy.utils;

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;

public class MyKnowledgeBaseFactory {
  public static KnowledgeBase
                createKnowledgeBaseFromDSL(String dslr,
			String dsl) throws Exception {

   KnowledgeBuilder builder =
            KnowledgeBuilderFactory
				.newKnowledgeBuilder();

     //Attention!!!!
     //Add DSL BEFORE DSLR
     builder.add(
              ResourceFactory.newClassPathResource(dsl),
						ResourceType.DSL);

     builder.add(
              ResourceFactory.newClassPathResource(dslr),
				ResourceType.DSLR);

     KnowledgeBuilderErrors errors = builder.getErrors();

      if (errors.size() > 0) {
	for (KnowledgeBuilderError error : errors) {
		System.err.println(error);
	}
	throw new IllegalArgumentException("Could not parse knowledge.");
      }
      KnowledgeBase knowledgeBase =
                KnowledgeBaseFactory.newKnowledgeBase();
      knowledgeBase.addKnowledgePackages(
                    builder.getKnowledgePackages());
      return knowledgeBase;
   }
}

Below is my Tester class:

package net.javabeansdotasia.casestudy.test;

import net.javabeansdotasia.casestudy.pojo.AccomodationBase;
import net.javabeansdotasia.casestudy.pojo.AccomodationRank;
import net.javabeansdotasia.casestudy.utils.MyKnowledgeBaseFactory;

import org.drools.KnowledgeBase;
import org.drools.runtime.StatefulKnowledgeSession;

public class Test {

   public static final void main(String[] args) {
     try {
        KnowledgeBase kbase =
               MyKnowledgeBaseFactory
		   .createKnowledgeBaseFromDSL(
                        "accomodation.dslr",
			 "accomodation.dsl");
	StatefulKnowledgeSession ksession =
              kbase.newStatefulKnowledgeSession();
	AccomodationBase accomBase =
                  new AccomodationBase(9, "Just Demo");
	AccomodationRank accomRank =
                  new AccomodationRank(9, "Just Demo");
	ksession.insert(accomBase);
	ksession.insert(accomRank);
	ksession.fireAllRules();
      } catch (Throwable t) {
	 t.printStackTrace();
      }
    }
}

As you may have noticed, in Drools 5 the process of loading the rule files (DSL and DSLR) and getting a working session is different to Drools 4. In Drools 5 there is a whole new set of APIs. Basically, main change is that Drools now is knowledge oriented, instead of rule oriented. It was a real step forward in order to support other forms of logic, such as work-flow and event processing. You can read about it in Drools 5.0 docs.

That it. Please note that the above example was tested by me and its working fine. I also included source files for the above example as Eclipse project. You can simply create a new Java project from this existing Ant build.xml file.

Also, I wanted to point out that in my Eclipse project setup my Drools binaries located under JAVA_HOME/lib/drools-5.0-bin/ (have a look at the build.xml)

Cheers

JBoss Security – JMX Console

I was reading about JBoss security today, and came across the following page:
JBoss Security vulnerability JMX Management Console. The guy tells how common is to come across servers on the Internet that run completely unsecured JMX-Console.

I gave it a try, typed few keywords in Google, and voilà -
around one third of the Google results on the first page were links to various servers that run completely unsecured JBoss and JMX-console. Having said that, I would like to point out that I did not attempt anything naughty or malicious.

Its still amazes me how careless some people are – leaving an open door for anyone to come in. Come on people, surely in this day and age we all know how important is to keep web applications secured. Don’t be lazy, its not going to take much of your time since securing JMX-console its such a trivial task.