Modifying Headers Depending on Annotation - cxf

I wanted to modify the outgoing headers on a client interface depending on the annotation on the request method. For example:
#Path("/myservices")
public interface MyService {
#GET
#Path("/get/something")
#Produces("application/json")
#MyAnnotation("value")
String getsomething(
#QueryParam("first_param") String firstParam,
#QueryParam("second_param") int secondParam);
The getsomething method has a annotation MyAnnotation, which an interceptor [out interceptor perhaps] can check if it exists and modify the headers accordingly. I am able to modify the headers in the out interceptor but how do I check for the annotation? The underlying class is no more and I suppose I am way beyond interface and dealing with raw request/response.
Is there any other way of doing this? I could place the annotation at the class level and before JAXRSClientFactoryBean.create. I could check the class annotation and stuff the headers into the client. However, I would prefer it at method level. Any suggestions? Note this is for client interface.

Related

Optional response body for rest client using RESTEasy

I'm writing a POC for Quarkus. I'm using this quick start guide to build a REST client. The REST service I'll be integrating with is third party. Here is a simple example of my current implementation:
#Path("/v1")
#RegisterRestClient
public class EmployeeApi {
#POST
#Path("/employees")
ApiResponse createEmployee(#RequestBody Employee employee)
}
This works fine. The issue I'm having is that the third party API will, depending on success / failure, return a response body. In the scenario it does fail, it provides details in the response body (ApiResponse) on why it was unsuccessful. When it succeeds, it returns nothing. This causes Quarkus to throw the following exception:
javax.ws.rs.ProcessingException: RESTEASY003145: Unable to find a MessageBodyReader of content-type application/octet-stream and type com.test.app.ApiResponse
I've tried to wrap ApiResponse in an Optional type but does not solve the problem. I see absolutely nothing in Quarkus / RESTEasy documentation that would indicate a work-around.
I'm wondering if I should be using javax.ws.rs.core.Response instead.
The problem is JaxRS tries to fit ApiResponse to a default return type being application/octet-stream
You should make sure to specify explicitly that you're returning application/json
This is possible using #Produces(APPLICATION_JSON) on top of your service.
Here is the correct code snippet
#Path("/v1")
#RegisterRestClient
public class EmployeeApi {
#POST
#Path("/employees")
#Produces(APPLICATION_JSON)
ApiResponse createEmployee(#RequestBody Employee employee)
}

How do I set CSV header in camel DSL?

I have one CSV file without header which is containing two value like
"lenovo","30000"
I want to set header in first row using camel DSL and pass it to another route, header is like:
"laptop","price"
My DSL route:
from("file:...?fileName=file1.csv&noop=true")
//Something I want to include string like this
.addLineInBody("laptop"+"price").append("\n")
.to("file:../?fileName=output.csv");
How can I do this in camel DSL?
I do not fully understand your header-problem. If you want to just prepend the CSV file with a static header a save it again as CSV you could simply use a Java bean to prepend the message body.
If you want to convert CSV to a data structure or vice versa you should check out the Camel CSV documentation: http://camel.apache.org/csv.html
Update:
You can write a java bean like this. The important part is the #Body Camel annotation to inject the message body into the method. See http://camel.apache.org/parameter-binding-annotations.html for more information about this.
Do the body manipulation as you like.
public class CsvHeaderEnricher {
public String enrichCsvHeader(#Body String messageBody) {
String enrichedBody = "YourHeader" + messageBody;
return enrichedBody;
}
}
Then you can call the bean in your route like this:
from("file:...?fileName=file1.csv&noop=true")
.bean(new CsvHeaderEnricher())
.to("file:../?fileName=output.csv");
You can also register the bean in the Spring context, autowire it into the Route class and use an instance variable instead of new
As long as your bean contains only one method, you don't need to tell Camel what method to use

Empty response from camel in cxf POJO mode

Below is my routing for a sample web service in camel and cxf.
from("cxf:http://localhost:9000/sampleService?serviceClass=com.sample.CommonIntf")
.id("wsProxy")
.bean(MyBean.class)
Simply I am passing input pojo object to bean. And inside bean I am setting the ws response. Here is the bean class.
#Handler
public SOut handle(SInput sin){
SOut s = new SOut();
s.setName(sin.getName());
s.setSurName("aa");
return s;
}
However althoug I can see input object is converted and delivered the handler method soap response is empty.
Here is my web service signature.
public interface CommonIntf{
SOut sampleMethod(SInput input);
}
My question is although my handler returns response, why response soap is empty ?
I think, you just not set exchange output body (request-reply pattern).
Try to modify your route like this:
from("cxf:http://localhost:9000/sampleService?serviceClass=com.sample.CommonIntf")
.id("wsProxy")
.to("bean:MyBean?method=handle");
MyBean class must be registered in bundle context.
<bean id="MyBean" class="com.sample.MyBean"/>
Try the following , define your CXF endpoint
[as per http://camel.apache.org/schema/cxf/ ] in a endpoint definition bean, in this refer the service class,
and refer the same id (for example wsCxfId)in the Camel route.
So the route will be as follows:
from("cxf:bean:wsCxfId")
.id("wsProxy")
.to("bean:MyBean?method=handle");
Hope this helps.

Resteasy: How does json extension get extracted from /customers.json

I don't understand how the below class is able to recognize the request /customers.json as the /customers path and able to extract and extract the json extension. There is no path parameters.
"Consider this
JAX-RS resource class:
#Path("/customers")
public class CustomerResource
{
#GET
#Produces("application/xml")
public Customer getXml() {...}
#GET
#Produces("application/json")
public Customer getJson() {...}
}
For this CustomerService JAX-RS resource class, if a request of GET /custom
ers.json came in, the JAX-RS implementation would extract the .json suffix and remove
it from the request path. It would then look in its media type mappings for a media
type that matched json. In this case, let’s say json mapped to application/json. It
would use this information instead of the Accept header and dispatch this request to
the getJson() method."
I got the official answer from author: "The specification does not define a facility for this, but most JAX-RS implementations support it."

How to get custom SOAP header from WCF service response in Silverlight?

I'm trying to get custom response message header in Silverlight application.
on server-side new MessageHeader added to response headers:
OperationContext.Current.OutgoingMessageHeaders.Add(MessageHeader.CreateHeader("headerName", "headerNS", "The header value"));
and I can see this header in Fiddler:
s:Envelope [
xmlns:s=http://schemas.xmlsoap.org/soap/envelope/
]
s:Header
headerName [ xmlns=headerNS ] The
header value
But, I can't find a way to read header value in Silverlight application service callback:
using (new OperationContextScope(proxy.InnerChannel))
{
var headers = OperationContext.Current.IncomingMessageHeaders;
// headers is null :(
}
Does anyone encountered with similar issue?
Getting SOAP headers in responses on Silverlight isn't as easy as it should be. If you use the event-based callbacks, you're out of luck - it just doesn't work. You need to use the Begin/End-style operation call, like in the example below.
void Button_Click(...)
{
MyClient client = new MyClient();
IClient proxy = (IClient)client; // need to cast to the [ServiceContract] interface
proxy.BeginOperation("hello", delegate(IAsyncResult asyncResult)
{
using (new OperationContextScope(client.InnerChannel))
{
proxy.EndOperation(asyncResult);
var headers = OperationContext.Current.IncomingMessageHeaders;
// now you can access it.
}
});
}
Notice that you cannot use the generated client (from slsvcutil / add service reference) directly, you need to cast it to the interface, since the Begin/End methods are not exposed (explicitly implemented) on the client class.
To get headers from http request try to use Client HTTP stack.
The easies way to do it is to register the prefix, for example:
WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);

Resources