3

I am very new to Java programming language and even newer to frameworks like JAX-RS and Hibernate.

In short I have to implement CRUD operations for one of the Hibernate entities in my JAX-RS application and need help for implementing Update operation in particular. Here are the Objectives that needs to be taken care of while implementing Update operation

  1. HTTP Request will have Content-Type header set to application/json
  2. Request Method to be used is PUT
  3. URL is something like - http://localhost:8080/bts/rest/cities/{id}
  4. Request Body will have Raw data - It will contain a String representing a json object with the new data that needs to be updated for the entity. Sample - {"name" : "Bengaluru"}
  5. The request will contain only those attributes of the entity object that needs to be updated and will NOT be a Complete representation of the new state of the object
  6. I have some default values defined for some of the properties of the entity as those will NOT be included NECESSARILY (can be included if the requester decides to overwrite defaults) with the CREATE request and I need to initialize them with some default values and these can be updated later as well through UPDATE operation

I have already implemented this but I am not happy with the way I have done the things here and seek help in order to refine my design and technique.

My ENTITY CLASS

@Entity
@Table(name="cities")
@JsonInclude(Include.NON_EMPTY)
@Where(clause = "del_status=1")
public class City {

@Id
@Column(name="city_id")
private Integer cityId;

@Column(name="name")
private String name;

@Column(name="status")
private int status = 1; //default value

@Column(name="del_status")
private int delStatus = 1;

public City () {
}

public City (Integer id, String name) {
    this.cityId = id;
    this.name = name;
    this.status = 1;
    this.delStatus = 1;
}

// Getters and Setters go here
}

My JAX-RS Resource Class

@Component
@Path("/cities")
public class CityResource {

@Autowired
@Qualifier("cityDaoImpl")
CityDao cityDao;

@Autowired
@Qualifier("transactionManager")
HibernateTransactionManager txManager;

@Context
UriInfo uriInfo;

@PUT
@Produces({MediaType.TEXT_PLAIN})
@Consumes({MediaType.APPLICATION_JSON})
@Path("/{cityId: \\d+}")
public Response updateCityObject(@PathParam("cityId") final Integer cityId, @Context HttpServletRequest request, InputStream requestBody) throws IOException{
    cityDao.updateCity(cityId, requestBody);
    return Response.status(Response.Status.OK).build();
}   

}

My CityDao Implementation Class

@Repository("cityDaoImpl")
public class CityDaoImpl implements CityDao {

    @Autowired
    @Qualifier("transactionManager")
    HibernateTransactionManager txManager;

    @Override
    public City getCityById(Integer id) {
        Session session = null;
        try{
            session = txManager.getSessionFactory().openSession();

            City city = (City) session.get(City.class, id);

            return city;
        } finally {
            if(session!=null && session.isOpen()){
                session.flush();
                session.close();
            }
        }
    }

    @Override
    public boolean updateCity(Integer cityId, InputStream requestBody) throws IOException{

        JsonObject cityJson = CityDaoImpl.getJsonFromRequestBody (requestBody);

        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setName("updateCity");
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

        TransactionStatus status = txManager.getTransaction(def);
        Session session = txManager.getSessionFactory().getCurrentSession();    

        City dCity = this.getCityById(cityId);

        if(cityJson.containsKey("name")){
            dCity.setName(cityJson.getString("name"));
        }

        if(cityJson.containsKey("status")){
            dCity.setStatus(cityJson.getInt("status"));
        }

        if(cityJson.containsKey("delStatus")){
            dCity.setDelStatus(cityJson.getInt("delStatus"));
        }

        session.saveOrUpdate(dCity);
        txManager.commit(status);

        return true;

    }

    private static JsonObject getJsonFromRequestBody (final InputStream requestBody) throws IOException {
        StringBuffer sb = new StringBuffer();
        String line = null;

        BufferedReader reader = new BufferedReader(new InputStreamReader(requestBody));
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }

        JsonObject jsonObject = Json.createReader(new StringReader(sb.toString())).readObject();

        return jsonObject;
    }
}

As you can see I am not using json-POJO auto un-marshalling provided by jackson because -

  1. I am not getting the complete representation of the entity state from the requestor.

  2. There are some attributes initialized with some default values in my Entity class.

Also, I have to manually search for the Keys included in the json request and call appropriate setter accordingly.

I have also read a lot about JPA EntityManager and persist and merge methods but I am not sure if and how can i make use of those techniques for my use case.

EDIT - My code is working fine functionally. I seek your help in order to fine tune the code and the technique which i have used here.

I am reading the request body using InputStream parameter and converting it to JsonObject instead of my POJO Entity Class (City).

I want to find out if there is a way to optimize the code here, or make it more readable using some features of Hibernate JPA or Jackson which I am not aware of.

Chesser
  • 455
  • 3
  • 9
  • You have provided a lot of background and your code. That is good! It is unclear (to me at least) what exactly your question is. What exactly is not working as you want it to be? What output do you get vs. what output you expect/require? – Rob Sep 11 '15 at 22:50
  • You could use declarative transactions and make use of the first level cache which would eliminate session opening, closing and so on. You could use a `MessageBodyReader` for auto-converting to `JsonObject` but apart from that, there is not so much you could do. – Christian Beikov Mar 12 '17 at 20:29

0 Answers0