Return Object as POJO

Dear experts,

Referring to my previous Topic "From JCR Node to JSON where @Thole wonderfully helped me find a solution.

I am able to get the Orang Object from the JCR successfully,.

Now I am trying return that object as a Response to a Rest API call.

I think HIPPO Bean object are serialized and if I return a POJO (Plain Old Java Object) ,it can be converted as a JSON or XML.

This codes is me trying to achieve that:

	@GET
	@Path("/test")
	public Response test(@Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception {
		Session session = null;
		JsonNode pojo = null;
		String result = null;
		try {
			HippoRepository repository = HippoRepositoryFactory.getHippoRepository("vm://");
			session = repository.login("admin","admin".toCharArray());	
			Node node = session.getRootNode().getNode("content/documents/xxxxxx/cubaorang/cubaorang[3]/xxxxxx:Orang");	
			HstRequestContext context = RequestContextProvider.get();		
			Orang org = (Orang) context.getObjectConverter().getObject(node);
			ObjectMapper mapper = new ObjectMapper();
			result = mapper.writeValueAsString(org);
		}catch(Exception e) {
			e.printStackTrace();
			throw  e;	
		}finally {
			session.logout();			
		}
		return Response.ok(result,MediaType.APPLICATION_JSON).build();
	}

BUT I keep getting a result that says

     [echo] Press Ctrl-C to stop the Cargo container...
[INFO] [talledLocalContainer] com.fasterxml.jackson.databind.JsonMappingException: Not supported yet. (through reference chain: org.finexus.xxxxxx.beans.Orang["node"]->org.hippoecm.repository.
impl.NodeDecorator["session"]->org.hippoecm.repository.impl.SessionDecorator["xaresource"]->org.hippoecm.repository.jackrabbit.XASessionImpl["principalManager"]->org.hippoecm.repository.security.Secur
ityManager$DefaultPrincipalManager["everyone"])
[INFO] [talledLocalContainer]   at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:388)
[INFO] [talledLocalContainer]   at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:348) ...

Where did I go wrong?

Hi Sola Lee,

I donā€™t think the Hippo Bean is serialized by default. Technically, this bean is not implemented Serializable interfact, and internally Hippo Bean have some internally methods to access the JCR.
In your message, you can see that the Orang having property name ā€˜nodeā€™ that is not Serializable.
So I think you can create a new plain POJO for this REST API purpose

1 Like

Thank you @Thole again.

I was barking up the wrong tree. Yes that make sense

Create a new POJO Object, copy the values from Orang into the new Object and return it.

Why did I think of that? Brillant, I will try it and share my codes again

Dear @ThoLe,

I found out how to do it.

Thank you so much. Here I will share my codes.

Now I am going to find out how to do an array of Orang out :smiley:

Create a Simple Java Class call Orang_POJO.java

package org.finexus.xxxxxx.beans;
public class Orang_POJO{
	public String nama;
	public String age;
	public Orang_POJO(Orang data) {
		nama = data.getNama();
		age = data.getAge();
	}
	public String getNama() {return nama;}
	public void setNama(String nama) {this.nama = nama;}
	public String getAge() {return age;}
	public void setAge(String age) {this.age = age;}	
}

Inside the OrangDTResouce.java I used this REST API method.

	@GET
	@Path("/test")
	public Response test(@Context HttpServletRequest request) throws Exception {
		Session session = null;
		Orang_POJO tmp= null;
		try {
			HippoRepository repository = HippoRepositoryFactory.getHippoRepository("vm://");
			session = repository.login("admin","admin".toCharArray());	
			Node node = session.getRootNode().getNode("content/documents/xxxxxx/cubaorang/cubaorang[3]/xxxxxx:Orang");	
			HstRequestContext context = RequestContextProvider.get();		
			Orang org = (Orang) context.getObjectConverter().getObject(node);
			tmp = new Orang_POJO(org);
		}catch(Exception e) {
			e.printStackTrace();
			throw  e;	
		}finally {
			session.logout();			
		}
		return Response.ok(tmp,MediaType.APPLICATION_JSON).build();
	}

When I started the HIPPO and call the rest API I get this result.

{"nama":"Sola","age":"48"}

Just to share the way I code for an array of Orang

	@SuppressWarnings("deprecation")
	@GET
	@Path("/test2")
	public Response test2(@Context HttpServletRequest request) throws Exception {
		Session session = null;
		Orang_POJO[] tmp= null;
		try {
			HippoRepository repository = HippoRepositoryFactory.getHippoRepository("vm://");
			session  = repository.login("admin","admin".toCharArray());			
			QueryManager queryManager = session.getWorkspace().getQueryManager();
			Query query = queryManager.createQuery(" SELECT jcr:path FROM xxxxxx:OrangDT WHERE hippostd:state='published' ",Query.SQL);
			QueryResult qResult =query.execute();					
			RowIterator rit = qResult.getRows();
			int count=0, max = (int) rit.getSize();
			tmp = new Orang_POJO[max];
			while (rit.hasNext()) {
				Row row = rit.nextRow();
				String targetPath = row.getPath();
				targetPath = targetPath.substring(1); // substring to remove 1st /
				targetPath += "/xxxxxx:Orang";
				Node node = session.getRootNode().getNode(targetPath);
				HstRequestContext context = RequestContextProvider.get();		
				Orang org = (Orang) context.getObjectConverter().getObject(node);
				Orang_POJO tmpo = new Orang_POJO(org);
				tmp[count]=tmpo;
				count++;
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw  e;
		} finally {
			session.logout();
		}
		return Response.ok(tmp,MediaType.APPLICATION_JSON).build();
	}

The result I get from calling the Rest API (http://localhost:8080/site/api-manual/OrangDT/test2) is

[{"nama":"Sola","age":"48"},{"nama":"Sorenx","age":"8"}]

For future reference, your solution would require you to do this for any type that includes your bean somehow (other generics, or as a property).

To have Jackson (the thing turning objects into JSON) always use the POJO wherever it encounters it, you can define a custom Serializer (@JsonSerialize as class annotation is the easiest). Then, in your custom serializer, create your POJO and just use the SerializerProvider to serialize it instead. If your Bean is ā€œBranchDocumentā€ and your POJO is ā€œBranchRepresentationā€, it mihgt look like this:

    @Override
public void serialize(final BranchDocument value, final JsonGenerator gen, final SerializerProvider provider) throws IOException {
    final BranchDocumentRepresentation represent = new BranchDocumentRepresentation().represent(value);
    provider.defaultSerializeValue(represent, gen);
}
1 Like

Dear @mriegler,

That is a good idea, I may try it and get back to you on this with my sample code.

Beautiful idea, for reference please go to https://www.baeldung.com/jackson-custom-serialization

Regards
Sola Lee