Pages

Showing posts with label neo4j. Show all posts
Showing posts with label neo4j. Show all posts

Friday, May 30, 2014

BIRT , Spring framework and Neo4j (BSN) - one more thing ~ Cypher

The main intent of the previous blog post (ref.1.: "BIRT , Spring framework and Neo4j (BSN)") was to describe sample BIRT integration into the Spring-Ecosystem with usage of Neo4j GraphDB over spring-data-neo4j project. 

GiTHub project: miko-spring-birt is waiting to be tested

I got some open questions there and some fun with running on different machines. The answer to the FeatureTwo (ref.1.), is still postponed, but it's coming, let's keep in mind. 

This additional blog post I would like to focuse on awesome features of Cypher and show some nice use-cases, how to get POJOs from Neo4j and deal with them. 
(moto: keep it simple just Cars and Garages)

Let's start with few words at the beginning. 
Cypher (intro) is a declarative graph query language which allows us to do lot of things (expressive and efficient queries , creating or updating GraphDB etc.). The main goal has been to create language suitable for developer and professionals (human readable declarations).  Cypher language has been also inspired by couple of different approaches (SQL, SPARQL for expressions and also some semantic details from other languages) as is visible from the updated demo (GiTHub miko-spring-birt)


BSN - Neo4jDB initial state
pic.1.:: initial state of Neo4jDB Cars are located in their Garages

By using Cypher language over native Neo4j interface (http://localhost:7474) written in AngularJS we can employ Cypher abilities to get specific NCar located in NGarage (pic.1.)
Let's find the 'Ford' node with its NGarage
CYPHER $: MATCH MATCH (ncar:NCar {make: 'Ford'})<-[:located]-(garage: NGarage {name:'GarageOne'}) return ncar, garage
Using defined command query we should get the following result (pic.2.)
pic.2.::NCar Ford is located in the GarageOne
We can also check which cars are located in the NGarege {name: 'GarageOne') by doing small changes into the Cypher query:
CYPHER $: MATCH MATCH (ncar:NCar {coreName: 'CAR'})<-[:located]-(garage: NGarage {name:'GarageOne'}) return ncar, garage
At the end we should get expected result (pic.3.):
pic.3.:: GarageOne has some cars
Now is good time to move to the next step. 

Let's merge Cypher abilities with Spring-Data-Neo4j GraphRepository interface implementation. Maybe it can be useful to make small comparison with Spring-Data-JPA project to see tiny differences between passing @Param into the @Query (service.3.)

To see how everything works we will create following simple services: 

1. service will find and return the Car made by Ford by using @Query annotation in repository service. We define 
public interface NeoCarService {
NCar findByMakeFord();
method which calls repository implemented service
@Query("MATCH (ncar:NCar) WHERE ncar.make = 'Ford' return ncar")
NCar findByMakeFord();
2. service is almost similar but the difference is new condition. It will return the car made by 'Ford' only if the car is located in the garage and return.  In this case we extend our service 1. by adding also reference to the car garage : 
public interface NeoCarService {
  ...
  NCar findByMakeFord();
  NCar findByMakeForWithGarage();
  ...
the service implementation
...
@Override
public NCar findByMakeForWithGarage() {
  NCar car = nCarEntityRepository.findByMakeFordWithGarage();
  car.setGarage(nGarageEntityRepository.findOne(car.getGarage().getId()));
  return car;
}
...
now do update to the related repository
public interface NCarEntityRepository extends GraphRepository<NCar> {
...
@Query("MATCH (ncar:NCar {make:'Ford'})<-[:located]-(garage) return ncar")
NCar findByMakeFordWithGarage();
...   
3. service will return the number of located cars in the chosen Garage by name. To do so is necessary to define new method provided by NeoGarageService
public interface NeoGarageService {
  ...
  int getCarNumberByName(String garageName);
  ...
and we can call over the repository directly Cypher query:
public interface NGarageEntityRepository extends GraphRepository<NGarage> {
  ...
  @Query("MATCH (g:NGarage)-->(nCar: NCar)-->(g_of_nCar) WHERE g.name = {name} RETURN count(g_of_nCar)")
  int getCarNumberByName(@Param("name") String name);
  ...
 
When you try Cypher query over Neo4j AngularJS interface you should see the following result (pic.4.)


pic.4.:: In the GarageOne are located following number of cars

Here is visible the tiny difference between passing @Param int the query in case of JPA CrudRepository
@Query("select c from Car c where u.make in :names")
Iterable<Car> findByNames(@Param("names")Set<String> makeList);
At the end of the story we create simple BIRT report by creating simple Report Design File (SampleNeCarGarage.rptdesing) and new link to the hellp.jsp to the BirtController.
The final result looks pretty cool, we know which model of Ford we do have. Additionally we know his location and Total number of Cars located at the same Garage (pic.5.). 

pic.5.:: Cypher in Action and giving us information where the Ford is and how many cars are located in the GarageOne => 3 (pic.3.)
Conclusion: 
Enjoy and have a fun with BIRT, Neo4j and Spring 

Thursday, May 29, 2014

bright future ... alias ... future posts

Whole life is one big studY
pic.1.: student for ever ~ we are all students
I was not active in blogging for last few years (pic.1.), I've been almost completely overloaded by work and focused on project to kick them out or make them just work. Some of them were mine and the rest for companies (pic.2.). 


connect dots together and move things forward
pic.2.: retrospective at GeeCON : connecting dot's together and moving forward
Overall big part of my heart belongs to cutting-edge technologies ... just like small child (never stop discovering bright future) (pic.2.). I've spent big portion of my time by studying Machine Learning possibilities because behind all this will be always clear math. (algebra, probability, statistics ... just fun and getting better in various predictions)(pic.3.)

pic.3.: One day the result of our investigations -> it just works (maybe)
This area is in one hand pretty awesome because it connects many branches together, not  just only math. world but also langues or any other technologies, concepts or methodologies (servers, databases , big data, map reduce etc.)

RaspberryPI traveler package
pic.4.: one of RaspberryPI traveler packages

This blog I would like to focuse on small powerful systems (RaspberryPi, CuBox ...), spring projects, redhat projects (Netty, Vert.x, WildFly, Infinispan etc.) , JetBrains (IntelliJ IDEA, etc.), ZeroTurnaround technologies (JRebel, etc.), GraphDatabases ( Neo4j, etc.), Languages (Java, Scala, Groovy, Ruby, Python etc.)  and many other opensource technologies like JavaFx or NetBeans....(MineCraft) ps: List is too Long (StackOverflow ;)  

Another intent of this blog is to create utilized collection of links I may need currently or in near future with demo apps.

And at the and of course to share some cool news from the Java Virtual Machine World
 (GeeCON: Let's move the Java World!)

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 :)