I was doing some research on Camel - CXf integration and am confused about the below scenario.
So i implemented a Rest Endpoint
#Path("/authenticate")
public interface Sample {
#GET
#Path("/handshake")
#Produces(MediaType.TEXT_PLAIN)
public Response handshake();
#POST
#Path("/login")
#Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
#Produces(MediaType.APPLICATION_JSON)
public Response login(LoginRequest request) throws JsonGenerationException, JsonMappingException, IOException;
}
And the implementation as below
public class SampleImpl implements Sample{
#Context
private HttpHeaders headers;
#Autowired
CamelContext context;
public Response handshake()
{
System.out.println("HandShake Executed Successfully");
return Response.status(Status.OK).entity("This is a Message after Routing").build();
}
public Response login(LoginRequest request) throws JsonGenerationException, JsonMappingException, IOException {
System.out.println("The Rquest objecr is Received "+request);
return Response.status(Status.OK).entity(mapper.writeValueAsString(request)).build();
}
}
The Route
<camel:from uri="cxfrs:bean:SampleRestEndPoint?bindingStyle=SimpleConsumer"></camel:from>
routes it into the implementation. But since the implementation returns a response object am confused how to build the routes around this.
Once the call comes into the implementation how can I execute the
other routes and sent a response back?.In this case the implementation returns a custom object.
How are the other routes attached to a CXF route?.
Should my CXF Implemenation always return a void type?. As i see
that, to get access to Exchange object camel need the return type to
be void
Do I completely ignore the implementation and go with the "to" steps
and modify it in exchange body for the required response?.
Any pointers will be appreciated.
Dude, take a look at this - http://bushorn.com/camel-cxf-geocoder-example/
The above example is not REST though, but usage of CXF with Camel route is same.
I will do these mandatory steps:
Avoid beans/custom classes - try to use the camel framework capabilities.
Use XML - Spring/Blueprint DSL
Please look at the following thread.
Apache Camel and web services
I have successfully implemented web service consumption using camel and Apache CXF. If you have doubts, I can help you out.
Thanks,
Gautham
#GauthamHonnavara - that is an implementation of a JS webservice with an assosiated processor however it doesnt assosiate any direct route to the endpoint.Also my question was specific to JAX-RS where you cannot generate a service class from wsdl.
Assume this use case that u need a customer to invoke the endpoint and then go through say another 5 steps, reach out to another webservice etc and then sent a response back. The above implementation sents a response back in the webservice implementation bean itself.
So to avoid this create a simple interface with the producer consumer etc, just like in my question and then make each method void if you want to inject the Exchange( if needed. ) and use below configuration
<!-- Created the CXF End Point For the Calls to Come IN -->
<cxf:rsServer id="RestEndPoint" address="/rest"
serviceClass="com.poc.camel.cxf.service.incoming.xxx"
loggingFeatureEnabled="true" loggingSizeLimit="20">
<cxf:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" >
<!-- <constructor-arg ref="customObjectMapper" type="org.codehaus.jackson.map.ObjectMapper"/> -->
</bean>
</cxf:providers>
</cxf:rsServer>
Trick is to use the service class tag. If the interface is provided there then it doesn't need a concrete implementation from CXF.
Hope this helps. Let me know
Related
I'm learning about Apache Camel routes in Spring Boot projects and I have a project that does extension from some endpoints. The endpoints are not in this project, only the extension is done here. The extension is done using #Consume from org.apache.camel in this way:
#Consume(uri = "direct:products.create.validate.interceptor")
public void executeCreate(RequestWrapper<Product> productWrapper) {
...
}
I try to understand how this direct:products.create.validate.interceptor is mapped to an endpoint from another service. Can somebody explain me how this #Consume annotation does the mapping?
Or another example is this:
#Consume(uri = "direct:listAccountsPostHook")
public void executeCreate(RequestWrapper<Account> accountWrapper) {
...
}
Where should I look to understand how they are mapped? In the controller of the other service? I can't find any example with #Consume. Thank you!
The #Consume annotation in Apache Camel is used to subscribe to a Camel endpoint and consume messages from it. The endpoint can be either a direct endpoint or any other type of endpoint such as a JMS queue or a REST endpoint, depending on your use case.
The endpoint URI, which is specified in the uri attribute of the #Consume annotation, determines where the messages are consumed from. In your example, direct:products.create.validate.interceptor and direct:listAccountsPostHook are both direct endpoints.
In Apache Camel, direct endpoints are in-memory endpoints that allow you to send messages directly to another endpoint in the same JVM. The mapping between the endpoint and the method that consumes the messages is done by Camel's routing engine.
More on Camel Direct endpoints you can read here.
To understand how the messages are being consumed, you should look at the Camel routes that are defined in your project. In a Spring Boot project, you can define your Camel routes in a RouteBuilder class. This is where you would specify the mapping between the direct endpoint and the method that will consume the messages.
For example, if you have a RouteBuilder class that looks like this:
public class MyRouteBuilder extends RouteBuilder {
#Override
public void configure() {
from("direct:products.create.validate.interceptor")
.to("bean:myBean?method=executeCreate");
}
}
In this example, the direct endpoint direct:products.create.validate.interceptor is mapped to the executeCreate method in the myBean bean. The ?method=executeCreate part of the to URI tells Camel to call the executeCreate method on the myBean bean when a message is received at the endpoint.
So, in short, you should look for the Camel routes in your project that define the mapping between the endpoint and the method that consumes the messages.
I'm working on a springboot service currently and it needs to have the ability to modify the incoming response body received from various web service calls made by itself.
I googled around a lot and could find info about servlet filters, spring interceptors etc. But all of them sit between this service and its calling clients.
But I'm looking for a component which can sit between this service and the other services that it calls. The closest one I could find was spring's ClientHttpRequestInterceptor, but it doesn't seems to have the ability to modify response body.
Client apps ---> 2. My Springboot service. ---> 3. Other web services
I need to have a component between 2 and 3 here.
Can someone please shed some light on this? Thank you.
P.S: Also I know jaxrs ClientRequestFilter does the trick, but I need a solution for spring RestTemplate based service calls and not for jaxrs based.
In Spring RestTemplate allows us to add interceptors that implement ClientHttpRequestInterceptor interface .
The intercept(HttpRequest, byte[], ClientHttpRequestExecution) method of this interface will intercept the given request and return the response by giving us access to the request,
ClientHttpRequestExecution argument to do the actual execution, and pass on the request to the subsequent process chain
public class BodyInterceptor
implements ClientHttpRequestInterceptor {
#Override
public ClientHttpResponse intercept(
HttpRequest request,
byte[] body,
ClientHttpRequestExecution execution) throws IOException {
ClientHttpResponse response = execution.execute(request, body);
response.getHeaders().add("Iphone_version", "proX");
return response;
}
}
Spring AOP can help in your scenario. It can act as a component before invoking another controller or component.
I have a requirement to intercept the REST API responses for out application and do something with them. One very obvious approach to achieve this is to define an annotation and interceptor at method level (so that it can be applied to the REST API methods). However, I could not find a way to extract/intercept the response code for API responses. I am very new to Java EE world, so might be missing something here, but didn't find anything on internet search either. Our application is based on standard JavaEE with CXF.
I have seen some examples with code similar to the following, but not sure how I can get the API response from that. Any help would be appreciated.
#AroundInvoke
public Object around(InvocationContext context) throws Exception {......
Suppose you are using the standard JEE solution, from the doc
#AroundInvoke
public Object logInvocation(InvocationContext ctx) throws Exception {
String class = ctx.getMethod().getDeclaringClass().getName();
String method = ctx.getMethod().getName();
Logger.global.entering(class, method, ctx.getParameters());
try {
Object result = ctx.proceed();
Logger.global.exiting(class, method, result);
return result;
}
catch (Exception e) {
Logger.global.throwing(class, method, e);
throw e;
}
}
The Object result = ctx.proceed(); is the result for you.
JAX-RS server filters
Use a ContainerResponseFilter from the JAX-RS API 2.0 to intercept responses or server side:
#Provider
public class CustomResponseFilter implements ContainerResponseFilter {
#Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException {
// Intercept the HTTP response and get the status code
int status = responseContext.getStatus()
}
}
The JAX-RS 2.0 API also provide the ContainerRequestFilter to intercept requests:
#Provider
public class CustomRequestFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Intercept the HTTP request
}
}
To bind the filters to resource classes and/or methods, use name binding annotations.
Registering server filters in Apache CXF
According to the Apache CXF documentation, the filters must be registered in the cxf.xml configuration file. This file must be in the classpath of your application.
Here's an example extracted from the documentation of what your CXF configuration file can be like when registering a filter:
<beans>
<jaxrs:server id="customerService" address="/">
<jaxrs:serviceBeans>
<bean class="org.CustomerService" />
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="authorizationFilter" />
</jaxrs:providers>
<bean id="authorizationFilter" class="com.bar.providers.AuthorizationFilter">
<!-- authorization bean properties -->
</bean>
</jaxrs:server>
</beans>
For more details, check the CXF documentation about configuration.
Although interceptors are a great way to do cross-cutting concerns for your application services, you are talking about a web application here. You are not looking at intercepting service request, you are looking at intercepting http requests.
Web applications use the servlet spec, and for such generic stuff you'd use #Webfilters.
These webfilters can get the entire request and response, including the status code, as they work on the transport level, and not on the application level.
Be mindful that the servlet spec is picky: you cannot easily read requests and responses without duplicating them, and it's a bit messy code. Google a bit for it (log http request, log http response) and you should find plenty of code to create a filter which can do that.
Hi you didn't mention what technology stack. If you needed something for client side you could use Spring and Spring's ClientHttpRequestInterceptor.
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
ClientHttpResponse response = execution.execute(request, body);
/**
* response.getStatusCode();
*/
return response;
}
I need to manage different versions that come in the URL of the Webservice. I'm using a common method in the Webservice for SOAP and REST, and when I tried to get the path in the endPoint class I got the correct path for REST, but not for SOAP(I got a null in this case), does anybody how to get the path in soap?
The url looks like: http://localhost:8083/webService/v1/test and the code is:
#Stateless
#WebService(endpointInterface = "ItestgEndpoint", serviceName="testService")
#Component("testEndpoint")
#Path("/webService")
#Consumes({MediaType.APPLICATION_XML})
#Produces({MediaType.APPLICATION_XML})
public class TestEndpoint implements ItestgEndpoint{
#PUT
#Path("/{version}/test")
#Consumes({MediaType.APPLICATION_XML })
#Produces({MediaType.APPLICATION_XML })
#WebResult(name="testResponse")
public testResponse testEvent(#WebParam(targetNamespace="http://test/web", name="message")
#RequestParam MessageClass message,
#WebParam(name="version") #PathParam("version") String version
) throws TimeoutException, EMSException, ValidationException, AuthenticationException {
logger.info(version);
}
I saw this post SOAP and REST Webservice with one implementation in Java EE, but it didn't solve my problem.
Thanks
SOAP has no "path" like REST has. Depending on the service toolkit you use (CXF, axis, ...) you may need to collect the information in the request that you can extract from the transport mechanism of the soap message. This may or may not be available to you.
Usually, you wire the SOAP service to a path in a configuration. For example in axis, you set the soap servlet dispatcher in the web.xml, same is for cxf. The actual service is then wired in the beans.xml or services.wsdd.
The SOAP handler finds the service by the name of the endpoint and will then send the call to that endpoint which will dispatch it to the right method. The method is in the transmitted SOAP header, not in the URI.
In REST, the identification of the target service/method is in the URI, not in the XML.
So, in my opinion, for SOAP, this is by declaration and the wiring is static, while in REST, you can have the version as a path parameter.
UPDATE: Since everything is possible if you just try hard enough :-) you could rewrite the dispatcher code to allow an extra path parameter on SOAP, maybe the available packages allow some kind of interceptor class, that allows you to rewrite the SOAP header to point to another endpoint, depending on a header attribute that you invent.
I have a REST api written with JAX-RS, and I need to add authentication to it. So far all the information I've been able to find about it has suggestions for doing it via spring, which I'm not using. Is there something already existing, or would it be easy to write, something that will let me annotate either a method, or the entire class which would force auth headers to be present?
I'm using tomcat6 and jersey, if that matters.
Something like:
#Path("api")
public class Api {
#GET
#AuthenticationRequired
public Response getInfo(...) {...}
}
I think you want import javax.annotation.Security.RolesAllowed;
The annotation itself looks like this
#Path("/helloworld")
#RolesAllowed({"ADMIN", "ORG1"})
public class helloWorld {
#GET
#Path("sayHello")
#Produces("text/plain")
#RolesAllowed("ADMIN")
public String sayHello() {
return "Hello World!";
}
}
I would manage security at the container level. Here's a good writeup if you happen to be using Apache CXF:
http://cxf.apache.org/docs/secure-jax-rs-services.html
And here's an example for Glassfish:
http://www.butonic.de/2010/06/18/a-simple-jax-rs-security-context-example-in-glassfish/
Here's one more link, which discusses JSR 250 annotations (e.g. #RolesAllowed):
http://www-01.ibm.com/support/knowledgecenter/SSEQTP_8.5.5/com.ibm.websphere.base.doc/ae/twbs_jaxrs_impl_securejaxrs_annotations.html