Thursday, May 29, 2014

BIRT , Spring framework and Neo4j (BSN)

Eclipse Business Intelligence and Reporting Tool simply BIRT is an open-source technology platform used to create data visualisation and cool reports that could be embedded into rich client and web application. Let’s make on step forward…

…The Spring Framework re-invented enterprise Java in the last decade, becoming the dominant programming model in Enterprise Java. Spring version 4 keeps it at the cutting edge of modern Java development and it works nicely with Java 8 and many other languages (Groovy, Scala …).
Let’s stay with Java 8 in this blog post and move forward …

Neo4j is the World leading graph database. The Graph databases are substantially different then RDBMS systems. Neo4j DB consists from the root node, child nodes, relationships, indexes , labels and properties. Probably the easiest way how to play and having a fun with Neo4j in JavaEE environment is to use spring-data-neo4j which enables POJOs based development. You get also access to Cypher Query langue… final move to the beginning  … 

GiTHub demo app : miko-spring-birt

@Query("MATCH (ncar:NCar) WHERE ncar.make = 'Ford' return ncar")
NCar findByMakeFord();
This blog post has been created as the side product of the BIRT integration into much bigger spring-ecosystem. In purposes of blog post I wanted to connect the example application with one of my favourite Graph Databases. Yeap, we are talking about Neo4j. The next reason was to test spring-data-neo4j project in case of operation up to the nodes. 

When you search internet for while you will maybe find couple of demos BIRT, Spring integration. Those demos are mostly out dated and no maven based. In purposes the my demo app I’ve taken official one done by Jason Weathersby and Josh Long. They have done great job! 
I’ve fully copied their *.rptdesign files which made whole demo much easier to prepare. 

You can go through theirs blog post HERE and get more information around as I’ve not touch BIRT, Spring Remote possibility  but it’s not hard to extend my demo app.

So what we do have in this demo: 

  • Integrating BIRT engines in Spring MVC
  • Accessing Spring Beans from the BIRT Viewer 
  • Creating simple BIRT, Spring and Neo4j eco-system.

and which versions we do use: 
Spring 4.0.2.RELEASE
Spring-Data-Neo4j 3.1.0.RELEASE
BIRT 4.3.1

Other technologies:
neo-community-server 2.0.0 and 2.0.3 
Tomcat 6.0.39
JBoss WildFly 8.1
Maven 3.2.1
JRebel 5.5.3
IntelliJ IDEA 13.1.2

The most important step is to share Spring ApplicationContext correctly. There are couple of ways how to achieve it. In our demo I have created Spring Controller bean BirtController that implements ApplicationContextAware.

@Controller
@RequestMapping("/reports")
public class BirtController implements ApplicationContextAware {

Over the spring beans instantiation process there is look up over couple of interfaces one of them is  ApplicationContextAware. This interface defines method setApplicationContext(ApplicationContext ctx) which we do use to catch  ApplicationContext  context and share it with BirtEngineFactory. 


public class BirtEngineFactory implements FactoryBean<IReportEngine>, ApplicationContextAware, DisposableBean { 

The class BirtEngineFactory has been created in purpose of BIRT Engine start up, proper shutdown. This class can used by other beans to get instance of the BIRT Engine. 

Let's jump to the another cool part. Neo4j Graph DB model. Here is Idea behind pretty simple. Sometime is everything about Cars. In our demo every Car needs to be in its Garage. 

in the package : com.miko.demo.birt.model.*

  • class Car represent face object provided by fake carService. This service is used by clicking on link 2. BIRT Report with FakeSpringService 
  • class NCar represents @NodeEntity with properties 
  • class NGarage represents @NodeEntity with properties and relation

  • NCar and NGarage are in relation. 
After deploying the demo app to the application server Tomcat or JBoss WildFly. You can test available options and see the appropriate result. 


Demo APP
pic. 1.: Deployed Demo app


I’ve created also couple of necessary JUnit tests in purpose to test correctness of app functionality. (TEST -> package: com.miko.demo.birt.repository.*). 
Before you run any test you should have your local Neo4j instance started and listening on http://localhost:7474

Conclusion
The demo provides guidelines how to integrate BIRT with Spring 4 eco-system based on MAVEN. Another great point is that the demo app provides the guide line how to use Neo4j to modelling Nodes, their relationships and display the result by using BIRT engine with Spring Beans. 

Some comment
pic. 2.: Correct relationships between Nodes
During demo app tests on different  neo-community-servers , I’ve discovered some “features”. The Feature One disallows to create expected relation between nodes (pic.2.) . The relationship then looks like one NGarage node contains all NCar nodes (pic.3.) which is completely incorrect.


pic.3.: Incorrect relationships between nodes


After having a discussion about Feature One with Neo4j team I decided next day to change my laptop (Laptop 1) and reproduce it again. On Laptop 1 I was able reproduce this Node Relation issue by simply switching between tested Neo4j servers. But on the Laptop 2 I was not able to reproduce it, this was big  surprise after so many successful reproduction tests. I left idea that Spring-Data-Neo4j contains bug/issue behind and focused my investigation on Java related problem (simply I took a look at my code ),  concretely Iterator Interface and its implementation. I don't want to go to the details maybe I'll come back to this topic latter but this is the result . 


public class NeoCarInGarageTest implements NGarageConsts {
...
//Iterrator Issue. Iterator over Collection has not been updated
NGarage tmpGarageOne = garages.iterator().next();
NGarage tmpGarageTwo = garages.iterator().next();
...

and here we have Iterator over Collection without losing updated references
public class NeoCarInGarageTest implements NGarageConsts {
...
//Correctly assigned
Iterator nGarageIterator = garages.iterator();
NGarage tmpGarageOne = nGarageIterator.next();
NGarage tmpGarageTwo = nGarageIterator.next();
...

Feature One is easy to fix. 

Let's move to the Feature Two which is probably the issue of spring-data-neo4j and fully reproducible on any of tested servers (pic.4.). The feature two is visible from the last line where NGarage has lost its name (name = null). This result is not according to the result from previous line (which looks correctly) but this line is done over the Id reference which I don't think is correct. 
@Service("neoCarService")
public class NeoCarServiceImpl
...
result.setGarage(nGarageEntityRepository.findOne(nCar.getGarage().getId()).getName());
...
pic. 4.: BIRT with Spring Beans And Neo4j

 
Final statement
I will keep you updated about the feature two, Enjoy and have a fun with BIRT, Spring and Neo4j :)

No comments: