I am trying to return POJO class reference to client in rest WS(CXF 3.1.2) as below,
Service method declaration :
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes({"application/xml", MediaType.TEXT_PLAIN})
@Path("/agentLogout")
public ResponseEvent agentLogout(String ext) {
ResponseEvent response= new ResponseEvent();
response.setDn(ext);
return response;
}
Client Code:
WebClient client = WebClient.create(REST_URI);
client.path("agentLogout").accept(MediaType.APPLICATION_JSON);
Response agentLogoutResponse = client.post("3101");
String responseStr=agentLogoutResponse.readEntity();
POJO:
public class ResponseEvent {
private String dn;
public String getDn() {
return dn;
}
public void setDn(String ext) {
this.dn=ext;
}
}
Question:
how i can retrieve/access the returned reference in client code ?
String responseStr=agentLogoutResponse.readEntity(); // Do i need to create the pojo class/interface in client code too..?
Whether this POJO reference rendered as JSON in CXF? if so how we can use it in client code?
Thanks,
1) You might want to have MessageBodyWriter<ResponseEvent>
on server side. You might need to register this @Provider
. This would enable your POJO to be written to server's output stream. For instance (not tested):
@Provider
class ResponseEventWriter implements MessageBodyWriter<ResponseEvent> {
@Override
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
@Override
public long getSize(ResponseEvent t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return t.getDn().length();
}
@Override
public void writeTo(ResponseEvent t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException,
WebApplicationException {
entityStream.write(t.getDn().getBytes());
}
}
2) You need to have MessageBodyReader<ResponseEvent>
on client side.
For instance:
@Provider
public class ResponseEventReader implements MessageBodyReader<ResponseEvent> {
@Override
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
@Override
public ResponseEvent readFrom(Class<ResponseEvent> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
throws IOException, WebApplicationException {
StringBuilder sb = new StringBuilder();
try(InputStreamReader isr = new InputStreamReader(entityStream)) {
char[] c = new char[1];
while (isr.read(c) != -1)
sb.append(c);
} catch (IOException e) {
//do something
}
ResponseEvent event = new ResponseEvent();
event.setDn(sb.toString());
return event;
}
}
You need to register this provider on client side. You do this for instance using JAXRS client, instead of cxf client (available since cxf 3), for instance with something like:
Client client = ClientBuilder.newClient();
client = client.register(ResponseEventReader.class);
Response agentLogoutResponse = client.target(/*whateveryourpath + */ "agentLogout")
.request().accept(MediaType.APPLICATION_JSON)
.buildPost(Entity.text("1301")).invoke();
Then you can read your entity as
ResponseEvent event = agentLogoutResponse.readEntity(ResponseEvent.class);
Say You have created interface(It could be auto generated using WADL2Java plugin) at client side.
public interface MyService{
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes({"application/xml", MediaType.TEXT_PLAIN})
@Path("/agentLogout")
public ResponseEvent agentLogout(String ext);
}
Create A singleton Class and Create instance of Service
public class CxfRestSingleton {
public static GenService obj;
public static GenService getInstance() {
if (obj == null) {
obj = JAXRSClientFactory.create("http://localhost:8080/api/hello", MyService.class, Arrays.asList(new JacksonJaxbJsonProvider()));
}
return obj;
}
}
**NOTE:**Here I'm using Jackson JAXB JSON proivder, which can marshal/unmarshal both xml and JSON you could use your choice of provider. An Jackson provider is not part of cxf so you need to include these dependency separately
And the You could access your pojo class as shown Below
CxfRestSingleton.getInstance().agentLogout(12345).getDn();