Showing posts with label Netbeans. Show all posts
Showing posts with label Netbeans. Show all posts

Sunday, 8 June 2014

A look at HypergraphDB (Part 2)

This post is a follow on to A look at HypergraphDB (Part 1) if you are unsure on how to set up HypergraphDB please refer to that post.

There will be one change here, instead of using:
HyperGraph graph = new HyperGraph("/home/mhoward/Hypergraph");

We will use:
HyperGraph graph = HGEnvironment("/home/mhoward/Hypergraph");  

The benefit to using HGEnvironment over creating a new graph manually is HGEnvironment keeps a record of all open graphs and will return an existing graph if it is open.

The first thing we will do is set up two plain Java objects to add to the graph, the first is Product.java and it looks like so:
 package com.markhoward.hypergraphexample;  
 public class Product {  
   private String name;  
   private String specs;  
   private double price;  
   /**  
    * Default constructor is needed by HypergraphDB to serialize.  
    */  
   public Product(){a  
   }  
   public Product(String name, String specs, double price){  
     this.name = name;  
     this.specs = specs;  
     this.price = price;  
   }  
   public String getName() {  
     return name;  
   }  
   public void setName(String name) {  
     this.name = name;  
   }  
   public String getSpecs() {  
     return specs;  
   }  
   public void setSpecs(String specs) {  
     this.specs = specs;  
   }  
   public double getPrice() {  
     return price;  
   }  
   public void setPrice(double price) {  
     this.price = price;  
   }  
   @Override  
   public String toString(){  
     return String.format("Product name: %s, product specs: %s, Product price: %.2f", getName(), getSpecs(), getPrice());  
   }  
 }  

The thing to note when creating the classes that will be persisted is, HypergraphDB follows the Java Bean specification, so your class will need a default (no args) constructor, it is a good idea to override hashcode and equals and also have matching getter and setter methods.

The second Java class is the Category class, it simply holds the name of the category:
 package com.markhoward.hypergraphexample;  
 public class Category {  
   private String name;  
   /**  
    * Default constructor is needed by HypergraphDB to serialize.  
    */  
   public Category(){  
   }  
   public Category(String name){  
     this.name = name;  
   }  
   public String getName() {  
     return name;  
   }  
   public void setName(String name) {  
     this.name = name;  
   }  
   @Override  
   public String toString(){  
     return String.format("Category: %s", getName());  
   }  
 }  

The aim is to add some products to the graph and link them to the relevant category, then query the graph for the product and get the category back.

I created a toString method to allow the results be printed directly to the console to make things easier, if there is no toString method the JVM may just print the memory address of the object.

So create a few Product and Category objects like so, add them to the graph and create a link between the Product and the relevant category.
 private void addSomeProducts(){  
     /*  
      * Create categories add them to the graph and save the handles.  
      */  
     Category digitalCamera = new Category(DIGITAL_CAMERA);  
     Category computer = new Category(COMPUTER);  
     HGHandle digitalCameraCategoryHandle = graph.add(digitalCamera);  
     HGHandle computerCategoryHandle = graph.add(computer);  
     /*  
      * Create Products and add them to the graph (saving the handles).  
      */  
     Product camera1 = new Product("Canon IXUS", "10 Megapixel, 3x Zoom", 100.00);  
     Product camera2 = new Product("Nikon Coolpix", "12 Megapixel, 3x Zoom", 120.00);  
     Product computer1 = new Product("Apple Macbook Pro", "2Ghz, 500GB", 1200.00);  
     Product computer2 = new Product("Dell XPS", "3Ghz, 1TB", 600.00);  
     HGHandle camera1Handle = graph.add(camera1);  
     HGHandle camera2Handle = graph.add(camera2);  
     HGHandle computer1Handle = graph.add(computer1);  
     HGHandle computer2Handle = graph.add(computer2);  
     /*  
      * Make a link from each product to the relevant category.  
      */  
     HGValueLink link1 = new HGValueLink("category", digitalCameraCategoryHandle, camera1Handle);  
     HGValueLink link2 = new HGValueLink("category", digitalCameraCategoryHandle, camera2Handle);  
     HGValueLink link3 = new HGValueLink("category", computerCategoryHandle, computer1Handle);  
     HGValueLink link4 = new HGValueLink("category", computerCategoryHandle, computer2Handle);  
     /*  
      * Add the link to the graph.  
      */  
     graph.add(link1);  
     graph.add(link2);  
     graph.add(link3);  
     graph.add(link4);  
   }  

Once these objects have been added to the graph, create a query like so:
 HGQueryCondition condition = new AtomTypeCondition(Product.class);  
 HGSearchResult<HGHandle> resultSet = graph.find(condition);  

The condition will simply return all products currently saved in the graph. The resultset that is returned is very similar to a ResultSet in JDBC, the results can be iterated over like so
 try  
     {  
       while(resultSet.hasNext()){  
         HGHandle productHandle = resultSet.next();  
         /*  
          * For each product traverse the graph starting with this   
          * product and print the results.  
          */  
         printCategory(productHandle);  
       }  
     }  
     catch(Exception exception){  
       /*  
        * Print any exceptions that occur, I have come across type casting  
        * problems, which would occur at runtime.  
        */  
       exception.printStackTrace();  
     }  
     finally{  
       resultSet.close();  
     }  

Note: be sure to close the resultset as if it is not closed it will cause the referenced objects to be locked, it will stop the graph being closed gracefully and if these objects are queried further the application will throw exceptions.

The resultset contains the handles which reference the objects contained in the graph. To get the product from the resultset you could do the following (instead of printCategory(productHandle)):
 Product product = graph.get(productHandle);  

To traverse the links from the product handle the printCategory method looks like so:
 private void printCategory(HGHandle productHandle){  
     /*  
      * Set up a depth first traversal starting with our product.  
      */  
     HGDepthFirstTraversal traversal = new HGDepthFirstTraversal(productHandle, new SimpleALGenerator(graph));  
     while(traversal.hasNext()){  
       Pair<HGHandle, HGHandle> current = traversal.next();  
       HGHandle categoryHandle = (HGHandle) current.getSecond();  
       System.out.println(graph.get(categoryHandle));  
     }  
   }  

I hope this post helps anyone starting out with HypergraphDB, be sure to check out the JavaDocs as they are very well documented. There is also some great documentation on the HypergraphDB website.

I have uploaded the complete source for this example to Github:
https://github.com/bark4mark/hypergraphexample

A look at HypergraphDB (Part 1)

According to the HypergraphDB website it is described as a "general purpose, open source data storage mechanism based on a powerful knowledge management formalism known as directed hypergraphs".

So you may be asking the question, what is a hypergraph. I found a relatively simple explanation on StackOverflow "Hypergraphs are like simple graphs, except that instead of having edges that only connect 2 vertices, their edges are sets of any number of vertices. This happens to mean that all graphs are just a subset of hypergraphs." - link (when I imagine what a hypergraph looks like I imagine graphs within graphs!)

What I really like about HypergraphDB is how easy it is to setup, so lets get into setting up a Java project in Netbeans, and recreating the example from the HypergraphDB website.

The first thing I did after opening Netbeans is create a new project, I chose to create a Java application from under the Maven menu (this will auto generate your pom.xml file). I then added the code below to the pom.xml before the ending project tag.

 <repositories>  
   <repository>  
    <id>hypergraphdb</id>  
    <url>http://hypergraphdb.org/maven</url>  
   </repository>  
  </repositories>  
  <dependencies>  
  <dependency>  
        <groupId>org.hypergraphdb</groupId>  
        <artifactId>hgdb</artifactId>  
        <version>1.2</version>  
   </dependency>  
   <dependency>  
        <groupId>org.hypergraphdb</groupId>  
        <artifactId>hgbdbje</artifactId>  
        <version>1.2</version>  
   </dependency>  
  </dependencies>  

When the pom.xml file has been updated, right click on the project and choose Build with Dependancies this will download the required jar files, now the project is set up you will need a folder to store your HypergraphDB, I made a folder in my home directory called Hypergraph for this example.


 public class HyperGraphExample {  
   public static void main(String args[]){  
     HyperGraph graph = new HyperGraph("/home/mhoward/Hypergraph");  
     HGHandle handle = graph.add("Hello World");  
     String hello = graph.get(handle);  
     System.out.println(hello);  
     graph.close();  
   }  
 }  

The line "HyperGraph graph = new HyperGraph("/home/mhoward/Hypergraph");" simply sets up the graph and data will be saved in the /home/mhoward/Hypergraph folder.

graph.add will add an object to your graph, it returns a handle which can be used to retrieve that object at a later stage using graph.get.

graph.close is called to close the database, on the website it is recommended that graph.close is called to reduce the chances of data corruption, they recommend wrapping the code in a try/catch and finally closing the database to ensure close always gets called.

In part 2 I will be looking at adding sample data to the graph and querying that data, using the built in query mechanism.


Saturday, 24 May 2014

Creating Rest Web Services the easy way with Java in Netbeans

Download Netbeans 8.0 from https://netbeans.org/downloads/ I got the Java EE version as it comes with Tomcat for deploying.

Create a new project in Netbeans, go to Maven > Project from archtype. You can search through all of the available archtypes for Jersey and choose Jersey quickstart webapp.

Find the web.xml file and add the following to enable POJO > JSON mapping.

<init-param>
     <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
     <param-value>true</param-value>
</init-param>

Now when you return any regular Java objects they will be automatically converted to JSON for browser consumption.

There is an example resource called MyResource.java, pay attention to the annotations as these are what powers your web services. Jersey uses all of the standard JAX-RS annotations for creating web services.

Select you project and hit the green play button, your default browser will open and you can view the HTML pages inside the Web Pages folder and also access any web services you have set up.

For more information on Jersey:
https://jersey.java.net/documentation/latest/user-guide.html