Home » Java » Enterprise Java » Bidirectional relationship with Jackson in REST web services in WildFly

About 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.

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
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy
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