set ClientRequestContext property dynamically in ClientRequestFilter - java

hey everyone i just want to know how can we set a property on ClientRequestContext object to a dynamic value when using ClientRequestFilter in jax-rs web service. just like this
Suppose i have an object
MyObject obj=new MyObject();
obj.nmae="simon";
obj.vendor=209;
Now i want to call a web service for which i create a jersey client and for that client i created the filter.Now what i want to know how to get my object passed down to clientFilter so i can set ClientRequestContext property to myObject?
#Provider
public class RequestClientFilter implements ClientRequestFilter {
#Override
public void filter(ClientRequestContext requestContext) throws IOException {
// how to set this to a variable value passed from a function in my code
requestContext.setProperty("test", "test client request filter");
//something along these lines
requestContext.setProperty("myobj",obj);
}
}
this is what is happening
MyObject obj=new MyObject();
obj.nmae="simon";
obj.vendor=209;
ClientConfig config = new ClientConfig();
config.register(EntityLoggingFilter.class);
config.register(GsonMessageBodyHandler.class);
config.register(ClFilter.class);
// config.property(ClientProperties.CONNECT_TIMEOUT, 1000);
config.property(ClientProperties.READ_TIMEOUT, 10000);
try {
Client client = ClientBuilder.newClient(config);
WebTarget webTarget = client.target("http://localhost:8081/ServicB").path("Register")
.path("Service");
System.out.println(webTarget.getUri());
Invocation.Builder invocationBuilder = webTarget.request().accept(MediaType.APPLICATION_JSON);
Response response = invocationBuilder.post(Entity.json("anything"));
System.out.println(response.getStatus());
String bresponse = response.readEntity(String.class);
if (bresponse == null) {
System.out.println("null response");
}
System.out.println(bresponse);
} catch (Exception ex) {
System.out.println(ex.getMessage());
}

You can register the filter as a class or an instance. If MyObject is just a one time object, you can simply pass the object through the constructor of the filter and then register it.
config.register(new RequestClientFilter(myObject));
If MyObject will change for each request, then you can also register the filter with the WebTarget instead. So with each different request, you can use a different object.
Response response1 = client.target(uri)
.register(new RequestClientFilter(myObjectOne))
.request()
.get();
Response response2 = client.target(uri)
.register(new RequestClientFilter(myObjectTwo))
.request()
.get();

Related

Send JSON in request OkHttp

Friends!
I have a simple HTTP request:
void postRequest(String postUrl,String phone, String message) throws IOException {
OkHttpClient client = new OkHttpClient();
//RequestBody body = RequestBody.create(JSON, postBody);
RequestBody body = new FormBody.Builder()
.add("phone", phone)
.add("message", message)
.build();
Request request = new Request.Builder()
.url(postUrl)
.post(body)
.build();
//System.out.println(request);
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
call.cancel();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("TAG",response.body().string());
}
});
}
How to properly implement sending a JSON object instead of simple parameters?
My attempts were unsuccessful, so I really need a hint.
The server that will accept JSON is running on AKKA-HTTP.
How do I send a request to this server correctly?
final case class Message(phone: String, message: String, service: String)
implicit val item = jsonFormat3(Message)
val queue: Queue[Message] = Queue()
val addMessage = post {
path("add_message"){
parameters("phone".as[String], "message".as[String], "service".as[String]){
(phone, message, service) => {
queue.enqueue(Message(phone, message, service))
complete("ok")
}
}
}
}
The easiest way to map and serialize your object in JSON format is to use the ObjectMapper class of jackson-databind library.
I personally use it to implement integration tests of RestControllers and it works very well. Here is the utility class I realized, you can take it and use it for your purposes:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public final class JsonUtils {
public static String json(Object obj) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(obj);
}
}
What you need to have is a POJO class which implements Serializable, and then pass the instance of your class to the json method and it will return the JSON format.
You can definitely use it for Android projects. I found many examples where you can add the dependency, but it depends whether you use Gradle or Maven.
Try that out!!!
How do you like this option?
I tried to implement it, but the send fails.
I'm missing an important detail. But I don't understand what it is.
// create your json here
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("KEY1", "VALUE1");
jsonObject.put("KEY2", "VALUE2");
} catch (JSONException e) {
e.printStackTrace();
}
OkHttpClient client = new OkHttpClient();
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
// put your json here
RequestBody body = RequestBody.create(JSON, jsonObject.toString());
Request request = new Request.Builder()
.url("https://YOUR_URL/")
.post(body)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
String resStr = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}

Testing Okhttp3 response body - java.lang.IllegalStateException: request == null

I have a method in class which does a HTTP GET call to get the response object and utilize this object further. The pesudo code is below:
public class ABC{
public method abc1(){
HttpUrl url = HttpUrl.parse("url").newBuilder()
.addPathSegment("path1")
.build();
Request request = new Request.Builder().url(url).build();
try (Response response = client.newCall(request).execute()) {
ResponseBody responseBody = response.body();
String body = responseBody.string();
//other logic
}catch (IOException e) {}
}
}
Now I am writing a unit test to test with different values in the response object (json object). This is as below:
public class ABCTest{
#Mock
private OkHttpClient mockHttpClient;
#Mock
private Call mockCall;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
#Test
public void abc1Test(){
ResponseObjectInJson responseObjectInJson = new ResponseObjectInJson(); //this is a object from my POJO class that i create in order to be received as a response
JSONObject jsonObject = new
JSONObject(responseObjectInJson);
ResponseBody body =
ResponseBody.create(MediaType.parse("application/json"),new
Gson().toJson(jsonObject));
Response.Builder builder = new Response.Builder();
builder.code(200);
Response response = builder.body(body).build();
when(mockCall.execute()).thenReturn(response);
when(mockHttpClient.newCall(any(Request.class))).thenReturn(mockCall);
//call the abc1() method here to see the response and behaviour
}
}
The problem is, when i debug, it throws InvocationTargetException when building the response builder.body(body).build();
And shows java.lang.IllegalStateException: request == null. I understand that i need to set request in the Response.Builder because when i evaluate the expression builder.body(body) in debugger, in the result it shows headers and body, but request is null.
i.e., builder.request(//a request here)
My question is:
1. In response why the request is needed?
2. How to set this? because i am unable to mock since its final.
Thanks in advance

Jersey Client returns HTTP 204 in a post method while trying to send jsonObject

Hey so I'm trying to send some json-object to a rest web service, then get the value of some specific keys, then process the data to finally return a new json-object which is going to be used in another place. Anyway, I'm getting HTTP 204 when I try to communicate with the service.
My rest service looks like this
#Path("/example")
public class PdfMaker {
#POST
#Path("/post")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response PruebasMet(JSONObject json) throws IOException, JSONException{
try{
String xml = json.getString("xml");
String plantilla = json.getString("plant");
//method that uses "xml" and "plant" and returns "pdf"
JSONObject response = new JSONObject();
response.put("pdf", pdf);
return Response.status(200).entity(pdfb64.toString()).build();
}catch(Exception e){
e.getStackTrace();
return null;
}
}
and I'm trying to communicate with this
public class Jersey {
public static String baseuri = "http://localhost:8080/PdfMakerGF/rest/example/post";
public static void main(String[] args) {
try {
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource webResource = client.resource(baseuri);
JSONObject objTest = new JSONobject();
objTest.put("xml","Data1");
objTest.put("plan", "Data2");
ClientResponse res = webResource.header("Content-Type","application/json;charset=UTF-8")
.post(ClientResponse.class, objTest.toString());
System.out.println("output..." + "\n");
System.out.println("Answer "+res);
} catch (Exception e) {
e.printStackTrace();
}
}
But the response that I receive is this one
Answer POST http://localhost:8080/PdfMakerGF/rest/example/post
returned a response status of 204 No Content
Obviously there is something wrong but can't see what is it.
Since I'm stuck with this. Any kind of help would be appreciated.
I'm using netbeans 8.1, Glassfish 4.1 and Jersey.
Thanks
If your server runs into an exception and goes to the catch block, it returns null which corresponds to HTTP 204 (No Content). As sisyphus commented, there should be some exception in the server standard output.
So you probably need to:
Return a different response code (e.g. INTERNAL_SERVER_ERROR or
BAD_REQUEST) in the catch block
Check why the server code is throwing
the exception
Most likely you get an Exception. I guess it is because you have "plant" in one place and "plan" in another.
okey so finaly it works what i need to change was the way that the service was reciving the data, with a inner class in my case, end up working like this ..
Class Aux{
String xml;
String plant;
//generate gettes and setters :)
}
#Path("/example")
public class PdfMaker {
#POST
#Path("/post")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response PruebasMet(Aux json) throws IOException,
JSONException{
try{
String xml = json.getXml();
String plant = json.getPlant();
//method that uses "xml" and "plant" and returns "pdf"
JSONObject response = new JSONObject();
response.put("pdf", pdf);
return Response.status(200).entity(pdf)).build();
}catch(Exception e){
e.getStackTrace();
return null;
}
}
and the client is ..
Client client = new Client();
WebResource wresource = client.resource("http://localhost:8080/PdfMakerGF/rest/example/post");
JSONObject json = new JSONObject();
json.put("xml", DATA);
json.put("plant", DATA);
ClientResponse response =
wresource.type("application/json").post(ClientResponse.class,
json.toString());
out = response.getEntity(String.class);
System.out.println("RES = "+response);
System.out.println("OUT = "+out);
out has the info that the service is Providing

How to send a SOAP request using WebServiceTemplate?

I am trying to send a request to a SOAP webservice. I read this tutorial and prepared the following code. However, I am going to send different requests to multiple SOAP webservices, whereas the tutorial focused on one request. How can I send SOAP request using WebserviceTemplate?
WebServiceTemplate
SoapMessage soapMsg = new SoapMessage();
soapMsg.setUsername("Requester");
soapMsg.setPassword("Pass");
soapMsg.setLanguageCode("EN");
Request request = new Request();
request.setDeparture("FDH");
request.setDestination("HAM");
Date date = new Date();
SimpleDateFormat frm2 = new SimpleDateFormat("yyyy-MM-dd");
request.setDepartureDate(frm2.parse(frm2.format(date)));
request.setNumADT(1);
request.setNumCHD(0);
request.setNumInf(0);
request.setCurrencyCode("EUR");
request.setWaitForResult(true);
request.setNearByDepartures(true);
request.setNearByDestinations(true);
request.setRronly(false);
request.setMetaSearch(false);
soapMsg.setRequest(request);
WebServiceTemplate webServiceTemplate = new WebServiceTemplate(). //how to create object and send request!
Object response = webServiceTemplate.marshalSendAndReceive(
"https://aaa5.elsyarres.net", soapMsg);
Response msg = (Response) response;
System.err.println("size of results of wogolo:"
+ msg.getFlights().getFlight().size());
You can use following code, you do not need to define anything in xml file.
try {
SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory(
MessageFactory.newInstance());
messageFactory.afterPropertiesSet();
WebServiceTemplate webServiceTemplate = new WebServiceTemplate(
messageFactory);
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("PACKAGE");
marshaller.afterPropertiesSet();
webServiceTemplate.setMarshaller(marshaller);
webServiceTemplate.afterPropertiesSet();
Response response = (Response) webServiceTemplate
.marshalSendAndReceive(
"address",
searchFlights);
Response msg = (Response) response;
} catch (Exception s) {
s.printStackTrace();
}
To send different SOAP requests to different SOAP services, you just need to make your WebServiceTemplate aware of all requests and responses it will have to process.
Create a Java class for each request and response like so:
package models;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
#XmlRootElement
public class FlyRequest implements Serializable {
private boolean nearByDeparture;
public FlyRequest() {}
public boolean isNearByDeparture() {
return nearByDeparture;
}
public void setNearByDeparture(boolean nearByDeparture) {
this.nearByDeparture = nearByDeparture;
}
}
(The #XmlRootElement is because we use JAXB marshaller below; see Jaxb reference for more info).
The setup of the template is done for example like so:
SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory(MessageFactory.newInstance());
messageFactory.afterPropertiesSet();
WebServiceTemplate webServiceTemplate = new WebServiceTemplate(messageFactory);
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("models");
marshaller.afterPropertiesSet();
webServiceTemplate.setMarshaller(marshaller);
webServiceTemplate.afterPropertiesSet();
"models" is the name of the package where the Request/Responses classes are, so that jaxb can find them.
Then you just instantiate the request of the class you want to perform the call, like so:
// call fly service:
FlyRequest flyRequest = new FlyRequest();
flyRequest.setNearByDeparture(false);
Object flyResponse = webServiceTemplate.marshalSendAndReceive("https://example.net/fly", flyRequest);
// call purchase service:
PurchaseRequest purchaseRequest = new PurchaseRequest();
purchaseRequest.setPrice(100);
Object purchaseResponse = webServiceTemplate.marshalSendAndReceive("https://example.net/purchase", purchaseRequest);
Similarly, you can cast the response objects into your JAXB classes defined above.
Here is an Example what you should be looking for
Soap has a lot of restriction unlike REST, It follows some standards which have to be meet before you get Network call to work,
But unlike Rest, in Soap if you have WSDL URL you can get all the information needed to call the Soap call
private final String NAMESPACE = "http://www.w3schools.com/webservices/";
private final String URL = "http://www.w3schools.com/webservices/tempconvert.asmx?WSDL";
private final String SOAP_ACTION = "http://www.w3schools.com/webservices/CelsiusToFahrenheit";
private final String METHOD_NAME = "CelsiusToFahrenheit";
this code was written in Android so you can ignore some part of it but I still kept it in answer so someone from android background can put a good use to it
Open [WSDL][1] in browser and check for the things which matter to call a remote method on server.
1
you will see an attribute targetNamespace whose value would be Namespace which you will use in this case Namespace is http://www.w3schools.com/webservices/
2
Now you require the name of the method this WSDL has four method each of the are int attribute s:element with the value is the name of the Method in this case four methods are FahrenheitToCelsius, FahrenheitToCelsiusResponse, CelsiusToFahrenheit, CelsiusToFahrenheitResponse
3
Now you have to fure out the SOAP Action which is NAMESPACE+METHOD
but WSDL also gives information about that as well, look for the tag soap:operation and it's soapAction attribute havs the Soap action as it's value in this case which we want to call is http://www.w3schools.com/webservices/CelsiusToFahrenheit
private class MyTask extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.show();
}
#Override
protected String doInBackground(Void... params) {
try {
SoapObject soapObject = new SoapObject(NAMESPACE, METHOD_NAME);
soapObject.addProperty("Celsius","12");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(soapObject);
HttpTransportSE httpTransportSE = new HttpTransportSE(URL);
httpTransportSE.call(SOAP_ACTION, envelope);
SoapPrimitive soapPrimitive = (SoapPrimitive)envelope.getResponse();
Log.d("TAG", "doInBackground: "+soapPrimitive.toString());
return soapObject.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String aVoid) {
super.onPostExecute(aVoid);
progressDialog.dismiss();
textView.setText(""+aVoid);
}
}
Assuming that your SoapMessage is marhsallable
To send the same message to multiple endpoints you only need to loop on the sending code and the request handler.
Something like this:
{
String endpoint = "https://aaa5.elsyarres.net"
WebServiceTemplate webServiceTemplate = new WebServiceTemplate().
webServiceTemplate.setDefaultUri(endpoint);
Object response = webServiceTemplate.marshalSendAndReceive(soapMsg);
// handle you are response as you are currently doing.
// Loop changing the endpoint as you need.
}
This code uses the Spring WebServiceTemplate
I tried many options and finally below one worked for me if you have to send soap header with authentication(Provided authentication object created by wsimport) and also need to set soapaction.
public Response callWebService(String url, Object request)
{
Response res = null;
log.info("The request object is " + request.toString());
try {
res = (Response) getWebServiceTemplate().marshalSendAndReceive(url, request,new WebServiceMessageCallback() {
#Override
public void doWithMessage(WebServiceMessage message) {
try {
// get the header from the SOAP message
SoapHeader soapHeader = ((SoapMessage) message).getSoapHeader();
// create the header element
ObjectFactory factory = new ObjectFactory();
Authentication auth =
factory.createAuthentication();
auth.setUser("****");
auth.setPassword("******");
((SoapMessage) message).setSoapAction(
"soapAction");
JAXBElement<Authentication> headers =
factory.createAuthentication(auth);
// create a marshaller
JAXBContext context = JAXBContext.newInstance(Authentication.class);
Marshaller marshaller = context.createMarshaller();
// marshal the headers into the specified result
marshaller.marshal(headers, soapHeader.getResult());
} catch (Exception e) {
log.error("error during marshalling of the SOAP headers", e);
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
return res;
}

JAX-RS CXF Exception wrapping

I would like to add an ExceptionMapper to CXF (2.6.1) which not only communicates the Response code, but also ships the exception in the payload format (I'm using JSON for now).
#Provider
public class CustomExceptionMapper
implements
ExceptionMapper<MyException>
{
...
#Override
public Response toResponse(MyException mex)
{
//I need something here which can convert mex object to JSON and ship it in response
// I want this to be de-serialized on client
//the following returns the status code
return Response.status(Response.Status.BAD_REQUEST).build();
}
...
}
Is there a way to do this ?
You may need to use #Produces to serialize your object to JSON like:
#Produces(MediaType.APPLICATION_JSON)
And then return Response.ok().entity(OBJECT).build();
The way that you can test your service:
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(getBaseURI());
ClientResponse response = service.path(ADDRESS).type("application/json").get(ClientResponse.class);
String s = response.getEntity(String.class);
System.out.println(s);
private static URI getBaseURI() {
return UriBuilder.fromUri(SERVER ADDRESS).build();
}

Categories

Resources