To pass an object to an another webservice - java

I have a webservice and from this webservice I should pass an obejct to an another service. I tried with #Pathparam and #QueryParam but Iam not getting the values in my service.
The code where I am passing the object is
public void MediatorCmpService() {
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(getBaseURI());
boolean flag = validateConfig(iFGetResponse);
if (flag) {
CustomerData customerData = transformationPayload(iFGetResponse);
TrilliumxmlProducer tri=new TrilliumxmlProducer(customerData);
}
System.out.println(flag);
}
Here I am passing the customerData Object to my TrilliumxmlProducer Service. But this Object is not getting passed to the TrilliumxmlProducer service
The code for the TrilliumxmlProducer is
#Path("/generateTrillium")
public class TrilliumxmlProducer {
// This method is called if XMLis request
public TrilliumxmlProducer(CustomerData customerData) throws JAXBException {
getXML(customerData);
// TODO Auto-generated constructor stub
}
#GET
#Produces({ MediaType.APPLICATION_XML })
public CustomerData getXML(#QueryParam("customerData") CustomerData customerData) throws JAXBException {
System.out.println("--------2----------" + customerData.getREQUESTTYPE());
return customerData;
}
}
Here My object is giving nullpointer exception. Can anyone help me here

You do not seem to be passing a QueryParameter in your request.
A PathParam is used to extract data from the Path, ie "endpoint/{id}/help" then the PathParam "id" would return whatever is in between "endpoint/" and "/help".
A QueryParam is used to extract data from the Query, ie "endpoint/help?id=" then the QueryParam would return whatever you have instead of in youe request.
Although technically legal, you should try to avoid mixing and matching, and just use one or the other.
Edit
Also, while I'm not certain, I'm pretty confident that you can't/shouldn't use an object graph to pass around your rest resources.

Related

How to internally call another restapi endpoint in quarkus controller class?

I need to call another rest api endpoint inside the controller class to provide filtered user list as a result. I can't find a way to call one rest api from another rest api.Controller class
This is my controller class method code:
#GET
#Path("/filter")
#Produces(MediaType.APPLICATION_JSON)
public Response filterByName(#QueryParam("page") int page, #QueryParam("first_name") String first_name,
#QueryParam("last_name") String last_name) {
try{
String uri = "https://reqres.in/api/users?page="+page;
//Flux<User1> users = restTemplate.getForObject(uri, User1.class);
Mono<List<User1>> result = users.filter(user-> user.getFirst_name().equals(first_name) && user.getLast_name().equals(last_name)).collectList();
return Response.ok(result).build();
}catch(Exception e) {
e.printStackTrace();
return Response.status(204).build();
}
}
My issue got resolved, I used microprofile rest client to create a proxy and called the endpoint from there. Thanks!
Take a look at the HttpClient class in java.
https://docs.oracle.com/en/java/javase/12/docs/api/java.net.http/java/net/http/HttpClient.html

Is there a way to retrieve objects with nested Lists via Spring's restTemplate

This is the object we are trying to retrieve:
// Lombok annotated
#Getter
#Setter
#ToString(callSuper = true)
public class GetTransactionsResponse {
public String name;
public List<Transaction> list;
}
We have an object that has metadata and a list of objects
We tried using spring's restTemplate in a method like the following:
public GetTransactionsResponse getTransactions(String token, Request request) {
var requestEntity = RequestEntity
.get(externalApiClient.getTransactionsPath())
.header(HttpHeaders.AUTHORIZATION, token)
.build();
return handleCall(requestEntity, GetTransactionsResponse.class);
}
private <T> T handleCall(RequestEntity<?> requestEntity, Class<T> clazz) {
try {
var result = restTemplate.exchange(requestEntity, clazz).getBody();
log.info("method: handleCall - requestEntity: {} - clazz: {} - result: {}", requestEntity, clazz, result);
return result;
} catch (Exception e) {
throw e
}
}
So we call the rest template but we are receiving null. Without nested data the previous method works but somehow returns null when using nested objects. Are we using rest template wrong?
First verify that your Rest API you created actually works. Test it with posman or ARC (Advanced Rest Client) - a plugin for chrome and see that you get the desired result. If it works, then you can send request to your API from any Http Client including Rest Template. If your API works but calling it from Rest Template doesn't then you will know that the problem is on your client side and you can try and figure out why. But first verify that your Rest API actually works and not returning null

Batch operations in JAX-RS

Context
I am currently working on a JavaEE project with a lot of existing resource based JAX-RS services. For this project we would like to have batch processing to prevent a lot of separate calls and, most importantly, to execute these different methods in a transactional context for rollback purposes with the native MongoDB driver. We want to avoid manually creating new methods for all possible combinations. I could not find any solution to this issue on Stack Overflow so I started analyzing the implementation of RESTEasy and I came up with the following solution.
Below a simplified/pseudo version of my code:
JAX-RS method
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path("execute")
public Response executeBatch(BatchRequestWrapper batchRequestWrapper) throws UnsupportedEncodingException
{
// Retrieve information from context
HttpServletRequest httpServletRequest = ResteasyProviderFactory.getContextData(HttpServletRequest.class);
HttpServletResponse httpServletResponse = ResteasyProviderFactory.getContextData(HttpServletResponse.class);
ServletContext servletContext = ResteasyProviderFactory.getContextData(ServletContext.class);
HttpResponse httpResponse = ResteasyProviderFactory.getContextData(HttpResponse.class);
SynchronousDispatcher dispatcher = (SynchronousDispatcher) ResteasyProviderFactory.getContextData(Dispatcher.class);
ResteasyHttpHeaders httpHeaders = (ResteasyHttpHeaders) ResteasyProviderFactory.getContextData(HttpHeaders.class);
ResteasyUriInfo uriInfo = (ResteasyUriInfo) ResteasyProviderFactory.getContextData(UriInfo.class);
// Create Mongo Client Session object and save it in a Singleton which contains a ThreadLocal object so that DAO layer can reuse the client session object for all methods.
// Iterate over all the methods and invoke dispatcher
for (BatchRequest batchRequest : batchRequestWrapper.getBatchRequests())
{
// Update URI based on specific endpoint
uriInfo.setRequestUri(URI.create(batchRequest.getUri()));
// Temporary use mock response for the response
MockHttpResponse response = new MockHttpResponse();
// Create httpservletinput message from RESTEasy lib to pass to the dispatcher. It will automatically resolve all parameters/methods etc.
HttpServletInputMessage request = new HttpServletInputMessage(httpServletRequest, httpServletResponse, servletContext, httpResponse, httpHeaders, uriInfo, batchRequest.getHttpMethod(), dispatcher);
// Set body in input stream if body is specified. This will inject the correct 'body' parameters in the methods. Query and Path parameters are already resolved in the method above.
if(!Strings.isNullOrEmpty(batchRequest.getBody()))
{
InputStream targetStream = new ByteArrayInputStream(batchRequest.getBody().getBytes(StandardCharsets.UTF_8));
request.setInputStream(targetStream);
}
// Actual invoke
dispatcher.invoke(request, response);
// Do something with response object
}
// Clean or abort session based on invoke result
return Response.ok().entity(null).build();
}
Request Object
public class BatchRequestWrapper
{
private List<BatchRequest> batchRequests;
public List<BatchRequest> getBatchRequests()
{
return batchRequests;
}
public void setBatchRequests(List<BatchRequest> batchRequests)
{
this.batchRequests = batchRequests;
}
}
public class BatchRequest
{
private String uri;
private String httpMethod;
private String body;
public String getUri()
{
return uri;
}
public void setUri(String uri)
{
this.uri = uri;
}
public String getHttpMethod()
{
return httpMethod;
}
public void setHttpMethod(String httpMethod)
{
this.httpMethod = httpMethod;
}
public String getBody()
{
return body;
}
public void setBody(String body)
{
this.body = body;
}
}
My solution works with one new REST method and let's me reuse all the existing JAX-RS annotated methods in the project. Before I actually fully implement this and bring it to production, I would like to know if this is the way to actually do this or are there better alternatives? I am not a big fan of the hard dependency on RESTEasy though.

Injection of HttpServletRequest in Jersey POST handler

Consider this case:-
I am injecting HttpServletRequest in a Rest Service like
#Context
HttpServletRequest request;
And use it in a method like:-
#GET
#Path("/simple")
public Response handleSimple() {
System.out.println(request.getParameter("myname"));
return Response.status(200).entity("hello.....").build();
}
This works fine but when I try to send it through POST method and replace the #GET by #POST annotation, I get the parameter value null.
Please suggest me where I am mistaking.
You do not need to get your parameters etc out of the request. The JAX-RS impl. handles that for you.
You have to use the parameter annotations to map your parameters to method parameters. Casting converting etc. is done automaticly.
Here your method using three differnt ways to map your parameter:
// As Pathparameter
#POST
#Path("/simple/{myname}")
public Response handleSimple(#PathParam("myname") String myName) {
System.out.println(myName);
return Response.status(200).entity("hello.....").build();
}
// As query parameter
#POST
#Path("/simple")
public Response handleSimple(#QueryParam("myname") String myName) {
System.out.println(myName);
return Response.status(200).entity("hello.....").build();
}
// As form parameter
#POST
#Path("/simple")
public Response handleSimple(#FormParam("myname") String myName) {
System.out.println(myName);
return Response.status(200).entity("hello.....").build();
}
Documentation about JAX-RS Annotations from Jersey you can find here:
https://jersey.java.net/documentation/latest/jaxrs-resources.html

Catching exceptions from a Jersey REST client thrown from a Spring MVC Rest service

I implemented a REST application using Spring MVC, Jersey and JAXB.
The client sends a ServiceRequest object which contains information about the request and receives a ServiceResponse object back with information about the response.
ServiceRequest
#XmlRootElement(name = "servicerequest")
public class ServiceRequest{
String serviceName = "AddUser"
public String getServiceName() {
return serviceName;
}
#XmlElement
public void setServiceName(String serviceName) {
this.serviceName = name;
}
}
ServiceResponse
#XmlRootElement(name = "serviceresponse")
public class ServiceResponse {
String responseCode;
public String getResponseCode() {
return responseCode;
}
#XmlElement
public void setResponseCode(String code) {
this.responseCode = name;
}
}
The client makes the call to the service using Jersey
ServiceClient
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(RESOURCE_URL);
ServiceRequest request = new ServiceRequest();
ServiceResponse response = service.path("addUser").type(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML).entity(request).post(ServiceRequest.class);
On the server side, the service gets the request, handles it and returns a ServiceResponse object.
#RequestMapping(method = RequestMethod.POST,
value = "/addUser",headers="Accept=application/xml")
#ResponseStatus(HttpStatus.OK)
public #ResponseBody ServiceResponse addUser(#RequestBody ServiceRequest request) {
ServiceResponse response = new ServiceResponse();
//Handle request
//service.addUser();
response.setCode("200");
return response;
}
The controller class shown above makes a call to another service class to handle the request (service.addUser()). This service class can raise a number of exceptions.
What i am not sure of is how best to handle them. After googling around, i found that i can use an ExceptionHandler as shown below:
#ExceptionHandler(NullPointerException.class)
#ResponseBody
public String handleException1(NullPointerException ex)
{
return ex.getMessage();
}
I can have the controllers extend a base class that has the exception handler.
A couple of questions regarding the above approach:
Do i have to create one handler for each exception type? There are so many exceptions that i need to handle so is it not possible to just have a generic handler for all exceptions?
As my controller returns an object of type ServiceResponse, what would be the object type that would be returned when an exception occurs?
The client expects to get an object of ServiceResponse type. How does it work if the response is an exception type?
And finally, i noticed that the ExceptionHanlder can only have a return type that is one of the following:
ModelAndView
Model
Map
View
String – interpreted as a view name
void, but only if the method writes directly to the response object
I thought i can create the ServiceResponse object in the ExceptionHandler and set the appropriate code and return the ServiceResponse object. This however is not possible if i cant return a ServiceResponse type in the excpetion handler.
Edit
I tried using the ExceptionHandler using a generic exception class as shown below
#ExceptionHandler(ServiceException.class)
#ResponseStatus(HttpStatus.BAD_REQUEST)
public #ResponseBody resolveServiceValidationException(ServiceException ex) {
System.out.println("In resolveServiceError");
ServiceResponse = new ServiceResponse();
response.setResponseException(ex.getMessage());
return response;
}
The exception is being caught but the ServiceResponse object is always null. All i get is the following message:
GET http://localhost:8080/myService/services/pingError returned a response status of 400 Bad Request
How can i access the response object when an exception is returned back?
Thanks
#ExceptionHandler annotation can take an array of classes as a parameter, so you can create only one (or more) handlers for multiple exceptions. Change the method signature to take the common ancestor of all handled exception classes as a parameter. Something along the lines:
#ExceptionHandler(value = {NullPointerException.class, AnotherException.class})
#ResponseBody
public String handleException1(Exception ex) {
return ex.getMessage();
}
In your case it'll be String, since you annotated it with #ResponseBody, but you probably want to change the returned http code to some error code. You can do it by adding
#ResponseStatus(value = HttpStatus.WHATEVER_CODE_YOU_WANT, reason = "Your message")`
annotation to your exception handler.
In case when http code returned by the call is greater or equal than 300, jersey client throws UniformInterfaceException. You can catch and handle it. The response type doesn't matter in this case, as the exception is thrown before the conversion.
update
Once you get a hold of UniformInterfaceException and change the exception handler on the server so it returns ServiceResponse as response body, then you can get the reponse using:
ServiceResponse response = uniformInterfaceException.getResponse().getEntity(ServiceResponse.class);

Categories