Enterprise Java

Bidirectional relationship with Jackson in REST web services in WildFly

This is an example for a Bidirectional relationship between Java entities in a REST web service with the Jackson API.

  1. Assume we have a bidirectional relationship between two entities Parent and Child.
     
     
     
     
     
     
     
    bidirectional_relationship_tables

  2. Using MySQL workbench to generate the SQL schema file for this two tables.
    DROP SCHEMA IF EXISTS `bidirectional_schema` ;
    CREATE SCHEMA IF NOT EXISTS `bidirectional_schema` DEFAULT CHARACTER SET utf8 ;
    USE `bidirectional_schema` ;
    
    -- -----------------------------------------------------
    -- Table `bidirectional_schema`.`PARENT`
    -- -----------------------------------------------------
    DROP TABLE IF EXISTS `bidirectional_schema`.`PARENT` ;
    
    CREATE  TABLE IF NOT EXISTS `bidirectional_schema`.`PARENT` (
      `PARENT_ID` INT NOT NULL ,
      `PARENT_CONTENT` VARCHAR(45) NULL ,
      PRIMARY KEY (`PARENT_ID`) )
    ENGINE = InnoDB;
    
    -- -----------------------------------------------------
    -- Table `bidirectional_schema`.`CHILD`
    -- -----------------------------------------------------
    DROP TABLE IF EXISTS `bidirectional_schema`.`CHILD` ;
    
    CREATE  TABLE IF NOT EXISTS `bidirectional_schema`.`CHILD` (
      `CHILD_ID` INT NOT NULL ,
      `CHILD_CONTENT` VARCHAR(45) NULL ,
      `PARENT_PARENT_ID` INT NOT NULL ,
      PRIMARY KEY (`CHILD_ID`) ,
      INDEX `fk_CHILD_PARENT_idx` (`PARENT_PARENT_ID` ASC) ,
      CONSTRAINT `fk_CHILD_PARENT`
        FOREIGN KEY (`PARENT_PARENT_ID` )
        REFERENCES `bidirectional_schema`.`PARENT` (`PARENT_ID` )
        ON DELETE NO ACTION
        ON UPDATE NO ACTION)
    ENGINE = InnoDB;
  3. Then we will insert some data to those two tables through this insert statements:
    INSERT INTO `bidirectional_schema`.`parent` (`PARENT_ID`, `PARENT_CONTENT`) VALUES ('1', 'First Parent');
    INSERT INTO `bidirectional_schema`.`child` (`CHILD_ID`, `CHILD_CONTENT`, `PARENT_PARENT_ID`) VALUES ('1', 'First Child', '1');
    INSERT INTO `bidirectional_schema`.`child` (`CHILD_ID`, `CHILD_CONTENT`, `PARENT_PARENT_ID`) VALUES ('2', 'Second Child', '1');
  4. The Maven dependencies for the Jackson API that are required for this example.
    <dependency>
     <groupid>com.fasterxml.jackson.core</groupid>
     <artifactid>jackson-annotations</artifactid>
     <version>2.5.2</version>
    </dependency>
    <dependency>
     <groupid>com.fasterxml.jackson.core</groupid>
     <artifactid>jackson-core</artifactid>
     <version>2.5.2</version>
    </dependency>
    <dependency>
     <groupid>com.fasterxml.jackson.core</groupid>
     <artifactid>jackson-databind</artifactid>
     <version>2.5.2</version>
    </dependency>

    Also, you can pick up your required Java EE dependencies from this link: https://wikis.oracle.com/display/GlassFish/Java+EE+7+Maven+Coordinates

  5. Using Eclipse to generate Entities from the above tables. File -> New -> Other, then from the wizard choose JPA Entities from Tables. A wizard will show up to create a connection to the schema that’s already created. Then select the two tables child and parent. Finally make sure that the “List generated classes in persistence.xml”.

    bidirectional_relationship_entities_generation_1

    You can proceed and follow the default settings but I chose the mapping settings as bellow:

    bidirectional_relationship_entities_generation_2

  6. There is nothing fancy about the persistence.xml. But there are two points to consider. First, I didn’t specify the persistence provider as I tend to use WildFly so the application will use the default persistence provider which is Hibernate. Second, I created a datasource on WildFly so that it can be used to connect to our schema. Thirds, I used EclipseLink that’s why I’m using this JPA provider org.eclipse.persistence.jpa.PersistenceProvider. Check this post to point WildFly to EclipseLink.
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
     <persistence-unit name="BidirectionalPU">
         <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
         <jta-data-source>java:jboss/datasources/Bidirectional_DataSource</jta-data-source>
         <class>com.ithinkisink.entity.Child</class>
         <class>com.ithinkisink.entity.Parent</class>
     </persistence-unit>
    </persistence>
  7. The first class that we will implement is the ApplicationConfiguration class that will point to the parent path of our coming REST services.
    package com.ithinkisink;
    
    import javax.inject.Singleton;
    import javax.ws.rs.ApplicationPath;
    import javax.ws.rs.core.Application;
    
    /**
     * 
     * @author Belal
     *
     */
    @Singleton
    @ApplicationPath("rest")
    public class ApplicationConfiguration extends Application {
    }
  8. Then we will create MyService class that will have two REST web services. The first will retrieve a parent with a children fetched. The second one is an opposite to this and will retrieve a child with it’s parent fetched.
    package com.ithinkisink.service;
    
    package com.ithinkisink.service;
    
    import javax.ejb.EJB;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
    
    import com.ithinkisink.entity.Child;
    import com.ithinkisink.entity.Parent;
    
    /**
     * 
     * @author Belal
     *
     */
    @Path("MyService")
    public class MyService {
    
     @EJB
     MyServiceDAO myServiceDAO;
     
     @GET
     @Path("/retrieveParentWithChildren")
     @Produces(MediaType.APPLICATION_JSON)
     public Parent retrieveParentWithChildren() {
      return myServiceDAO.retrieveParentWithChildren();
     }
     
     @GET
     @Path("/retrieveChildWithParent")
     @Produces(MediaType.APPLICATION_JSON)
     public Child retrieveChildWithParent() {
      return myServiceDAO.retrieveChildWithParent();
     }
    }
  9. Then we will create ServiceDAO and notice that the EntityManager is injected with a connection to the persistence unit that we already defined in the persistence.xml. I passed the name of the persistence unit to make this point clear. But you can just use the annotation @PersistenceContext without specifying the unitName attribute then it will use our persistence unit because there is no other persistence unit defined in our application.
    package com.ithinkisink.service;
    
    import javax.ejb.Stateless;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import javax.persistence.Query;
    
    import com.ithinkisink.entity.Child;
    import com.ithinkisink.entity.Parent;
    
    @Stateless
    public class MyServiceDAO {
     
     @PersistenceContext(unitName="BidirectionalPU")
     protected EntityManager entityManager;
     
     public Parent retrieveParentWithChildren() {
      int parentId = 1;
      Query q = entityManager.createQuery("SELECT p FROM " + "Parent " + "p JOIN FETCH p.childs WHERE p.parentId = :parentId ");
      q.setParameter("parentId", parentId);
      return (q.getResultList().size() > 0) ? (Parent) q.getResultList().get(0) : null;
     }
     
     public Child retrieveChildWithParent() {
      int childId = 1;
      Query q = entityManager.createQuery("SELECT c FROM " + "Child " + "c JOIN FETCH c.parent WHERE c.childId = :childId ");
      q.setParameter("childId", childId);
      return (q.getResultList().size() > 0) ? (Child) q.getResultList().get(0) : null;
     }
    }
  10. Now that our application is ready for testing will add it to the WildFly server. Then starting the server should be successful.
     
    bidorectional_relationship_wildfly
  11. For the sake of simplicity, I used Postman to test the running REST web services. So bellow are screenshots from the result on Postman.
     
    bidirectional_rest_1
     
    bidirectional_rest_2

Belal Galal

Belal is a full stack Java EE Developer with a good grasp of key skills like Analysis, Architecture and System Administration. He worked in different scale projects in a variety of domains such as inventory management, aerospace, finance, banking and telecom.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button