Dear experts,
Referring to my previous Topic "From JCR Node to JSON where @Thole wonderfully helped me find a solution.
Dear experts,
I need you advise.
Objective :
Create a complex document (using compund type) and generate the api-manual with it.
HIPPO CMS can do the following:
Create the complex data structure via the CMS interface (compound type and document type)
Generate the java files via Bean Writer
Generate generic API even for this compund type.
BUT HIPPO CMS cannot generate the api-manual for such complex type.
This is how I did it.
Create a component type call Orang (Person in Malay) and inā¦
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?
ThoLe
November 7, 2018, 8:32am
2
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
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
mriegler:
represent
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