Apache Camel - http Producer don't use GET-Method with enrich Pattern - java

I have a RESTful Webservice which I want to use with a content enricher in a Camel-Route.
See this similar Code:
from("direct:in") // Here comes XML
.to("validator:something.xsd") // validate it
.unmarshal("something-jaxb") // put it into a POJO
.setHeader(Exchange.HTTP_URI, simple("http://localhost:12345/restws/${header.foo}")) // Create the dynamic URI with simple
.setHeader(Exchange.HTTP_METHOD, constant("GET")) // set the HTTP-Method to use
.enrich("http://dummy", new MyAggregator()) // fetch some Information from a Restful Webservice
.to("direct:out"); // send the Message to another route
If I run this, I get the following error:
No type converter available to convert from type: de.my.Class to the required type: java.io.InputStream with value de.my.Class#620ee765.
It seems to me, he tries to send the body of the Exchange to the http-Endpoint, although I set the HTTP-Method to GET. I've read the documentation (https://camel.apache.org/http.html) and below Calling using GET or POST it describes that the Algorithm which selects the Method first look at the Header (1. Use method provided in header).
I found some workarounds, which describes how to move the body to a Exchange-property and move it back again after the Webservice-Call, but this can't be it...
EDIT:
Like Claus Ibsen mentioned enrich doesn't support dynamic uris. Fixed this in the example!

Neither enrich nor pollEnrich supports dynamic uris for their endpoints. Instead of using enrich, you can use the recipient list which support dynamic uris, and the aggregation strategy as well.

If it's "full of lists" of resources, sounds like you would want to split the lists and do a get on each resource

What's in the pojo? Your GET parameter should be a resource identifier and query parameters. That requires a custom converter.
http://fusesource.com/docs/esb/4.2/rest/RESTIntro.html
maybe consider using restlet instead... it's easier I think.
http://camel.apache.org/restlet.html

Related

How to have different JSON responses registered for a GET call

GET http://localhost/foo/api/v1/bars/:id
How to have different JSON responses registered for a GET call. We would like the GET call to return a separate response based on whether a CLI is invoking or the user interface is calling the API by passing a query parameter. But how do we register different serializers dynamically on the response.
You can use a User-Agent request header to identify the application doing the request. There are good tutorials to check how to access the headers in Spring, like this Baeldung one.

Is any additional attributes required to force the java type in spring integration

We are using spring-integation (xml based configuration), In which we are performing below steps
Convert the payload (java-object) to json
Make the rest api call
Convert back to java-object
<int:object-to-json-transformer content-type="test.Request" input-channel="objectToJsonChannel" output-channel="apiChannel"/>
<int-http:outbound-gateway id="apiChannel"
request-channel="apiChannel"
reply-channel="jsonToObjectChannel"
....
/>
<int:json-to-object-transformer type="test.Response" input-channel="jsonToObjectChannel" output-channel="responseChannel"/>
Above code works till spring-integration version 5.1. When I upgrade to 5.2. It starts to throw the exception as
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [test.Request] to type [test.Response].
I have noticed that object-to-json-transformer add class type on the header with key json__TypeId__. Then it uses that class type for json-to-object-transformer.
But it is expected that type attribute mentioned on json-to-object-transformer should be used if mentioned.
Please suggest on fixing this issue or Is it really bug on spring integration (5.2).
Consider to add a <header-filter header-names="json_*" /> before calling your REST service. The <int:object-to-json-transformer> populates JsonHeaders to let downstream to know what the real type of JSON we curry in the payload.
A <int:json-to-object-transformer> prefers those headers instead of static type option.
But since the payload is already a different representation than those request headers it does a wrong thing.
I would suggest an option on the <int:json-to-object-transformer> to make a preference, but that would not be fully logical. Since we have changed a payload, it would be better to change its respective headers. Otherwise we just lying to ourselves.
On the other hand a HTTP Outbound Gateway can take care for your to convert request into a JSON for network and back from JSON response to some POJO type.
See https://docs.spring.io/spring-integration/docs/5.2.3.RELEASE/reference/html/http.html#http-outbound and its expected-response-type. As long as a contentType header is an application/json, you are good to avoid those <int:object-to-json-transformer> & <int:json-to-object-transformer>.

Rest api - update single field of resource

Lets say I have rest endpoint for my Driver resource.
I have PUT method like this
myapi/drivers/{id}
{body of put method}
I need to add functionality which will allow to 'enable' and 'disable' driver
Is it good idea to create new endpoint for that like this?
PUT myapi/drivers/{id}/enable/false
or it is better to use existing endpoint ? One problem with using existing endpoint is that driver has lot's of fields(almost 30) and sending all those fields just for updating only 'enabled' or 'disable' driver is something overkill.
What do you think?
This is exactly what the HTTP method PATCH is made for. It is used in cases where the resource has many fields but you only want to update a few.
Just like with PUT, you send a request to myapi/drivers/{id}. However, unlike with PUT, you only send the fields you want to change in the request body.
Creating endpoints like myapi/drivers/{id}/enable is not very RESTful, as "enable" can't really be called a resource on its own.
For an example implementation of a Spring PATCH endpoint, please see this link.
Use PATCH Http metod to update one field
PATCH myapi/drivers/{id}/enable

JAX-RS: retrieve alternate format based on URL pattern

I have a simple JAX-RS service running in a Tomcat 6 container. Is it possible to display not only text but XML in the browser, in a comparable manner as in Rails by appending .xml or .json?
The service I have is based on this tutorial.
Short answer is no, JAX-RS does not allow you to switch the response content type simply by appending 'xml' or 'json' to the URL.
The specification explicitly defines how content negotiation happens - via the Accept HTTP header from the client side, matching with the #Produces annotation on the server side. So going by the spec, if you want to get a different content type then you would specify as such in an Accept header, and that content type would be returned (as long as the server supports it).
Having said that, JAX-RS implementations are free to implement custom (non-portable) extensions to support behavior similar to what you describe. An example would be RESTEasy, which allows you to define the desired content type as a query parameter Section 17.2 - Query String Parameter-based negotiation.
You could also design your resource classes to easily support the desired behavior - some examples can be seen in the Apache CXF Content Negotiation guide.

Store Axis raw XML request/response in session (to be used in JSP)

How, if possible, do I get the raw XML request/response that is invoked/retrieved by Axis in my application?
I'm using WSDL2Java that is included with Axis to generate the Java stubs.
EDIT:
What I currently have is an app that uses Axis to handle the remote API calls.
One of the requirement is to 'store' all the XML request/response from these calls in the session so that it will be available in the JSP (for debugging purposes). How can I achieve this?
I tried writing a custom handler that extends BasicHandler but in that handler, I still can't get the HttpServletRequest/HttpServletResponse pair from the MessageContext
After a while searching its as simple as this:
//After your _call.invoke(...);
//Request
String request = _call.getMessageContext().getRequestMessage().getSOAPPart().getEnvelope().getBody().toString();
//Response
String response = _call.getMessageContext().getResponseMessage().getSOAPPart().getEnvelope().getBody().toString();
where _call is org.apache.axis.client.Call
Then you can save it in a file where you want...
Why don't you write a server side soap handler, get hold of MessageContext and I believe there is a way to get hold of the payload from there. If you want to pass it to downstream then put it in thread local. See e.g. of handler here
I end up using the solution described in this question
Basically, I use it to get a hold of the HttpServletRequest and from there I set the proper item in the session.

Categories