Apache CXF DSOGI on Karaf + #Context UriInfo - dosgi

I am trying to create a RESTful web service in Karaf 4.0.8 with Apache CXF DOSGI. I am trying to add #Context in my implementation. How to do it?
#Component(immediate = true, property = {
"service.exported.interfaces=*",
"service.exported.configs=org.apache.cxf.rs",
"org.apache.cxf.rs.provider=com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider",
"org.apache.cxf.rs.address=/integr" })
public class AccountRestService implements AccountWebUserIdResource {
#Context
private UriInfo context;
...
}
UriInfo is not getting injected properly.

REST API Interface you need to add your #Context
#GET
#Path("{memberid}")
#Produces({"application/json"})
MembersResource.GetMembersByMemberidResponse getMembersByMemberid(
#PathParam("memberid") String memberid,#QueryParam("fields") String fields,
#Context javax.ws.rs.core.UriInfo uriInfo) throws Exception;

Related

Reading annotations defined on interfaces and create bean classes using annotation values

I am trying to create http client on the fly from jaxrs annotations provided on the interface for each api.
public #interface RestClient {
String baseUrlKey();
}
#Component
#RestClient(baseUrlKey="NOTIFICATION")
#Path("/notification/")
public interface NotificationClient {
#Path("/")
#POST
#Produces("application/json")
#Consumes("application/json")
public abstract NotificationResponse create(NotificationEntry entry);
}
Now, I am trying to write another class which is trying to find all interfaces annotated with #RestClient. I cant seem to find any solution for this. All application context methods seem to return classes which can be instantiated. Is there any way I can load this interface and create bean instance of apache http client on the fly and register with application context.
Here is the bean initializer class -
public class RestClientBeanProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger(RestClientBeanProcessor.class);
#Autowired
RestTemplate restTemplate;
#Autowired
ApplicationContext applicationContext;
#PostConstruct
private void registerClientBeans() {
Map<String, Object> beans = applicationContext.getBeansWithAnnotation(RestClient.class);
LOGGER.info("Registering client beans for - " + beans);
}
}
My beans object is empty. Spring is unable to tell me list of interfaces asked by my query.

Spring RestEasy interceptor

I have a Spring boot application with resteasy-spring-3.0.19 and jboss-jaxrs-api_2.0_spec-1.0.0.
I would like to intercept all the rest calls for authorization.
The interceptor is not getting invoked. Also, How can i get the target method #Path annotation value in the interceptor.
Do I need to register this in the Spring boot app?
#Provider
public class AuthorizationtInterceptor implements ContainerRequestFilter{
/**
*
*/
public AuthorizationtInterceptor() {
// TODO Auto-generated constructor stub
}
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
String method = requestContext.getMethod();
UriInfo uriInfo = requestContext.getUriInfo();
// Need the target method #Path annotation value ....
}
}
Target Rest class,
#Named
#Singleton
#Path(ROOT_PATH)
public class WebController {
#GET
#Path(TEST_PATH)
#Produces(MediaType.APPLICATION_JSON)
public Response getUser(#Context final HttpServletRequest request) {
}
}
In a post-matching filter (a filter without the #PreMatching annotation), you can use ResourceInfo to get the matched resource class and the resource method.
Inject ResourceInfo in your filter using the #Context annotation:
#Context
private ResourceInfo resourceInfo;
Then get the resource class and extract the #Path annotation:
Path path = resourceInfo.getResourceClass().getAnnotation(Path.class);
To get the resource method, use:
Path path = resourceInfo.getResourceMethod().getAnnotation(Path.class);
Depending on what you are trying to achieve, instead of comparing the value of the #Path annotation for authorization purposes, you could consider binding your filter to a set of resource classes or methods. See more details in this answer.
Depending on how you are setting up your application, you may need to register the filter in your Application subclass or in your web.xml deployment descriptor.

Cannot inject ResourceInfo into ContainerRequestFilter

I'm trying to implement a ContainerRequestFilter that checks some stuff. Ultimately, it shall authenicate a token, but I'm not there yet. The filter runs on a Grizzly HTTP Server (Grizzly 2.3.4) and sits in front of a JAX-RS resource (Jersey 2.0). I am also using Guice 3.0.
When I'm trying to inject javax.ws.rs.container.ResourceInfo into the filter, it is null.
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import java.io.IOException;
public class MyRequestFilter implements ContainerRequestFilter {
#Context
private ResourceInfo resourceInfo;
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
String method = containerRequestContext.getMethod();
System.out.println("method = " + method);
if("OPTIONS".equals(method)) return;
System.out.println("DO SECURITY");
}
}
Injecting the request into a JAX-RS resource, the injection is successful and I can work with it.
What am I doing wrong?
To enable injection in ContainerRequestFilter you have to annotate it as #Provider, then it works
#Provider
public class MyRequestFilter implements ContainerRequestFilter {
#Context
private ResourceInfo resourceInfo;
...
}

How do I create a sub-resource with spring dependencies #autowired with apache cxf

I can't figure out how to get spring to autowire dependencies in a sub resource. I need to specify some request state to the sub resource. I'll also need access to cxf managed #Contexts.
If I have a class
#Path("/resource/")
public class Resource {
#Autowired
private dependency
#Path("{id}/sub/")
public getSub(#PathParam("id") String id){
// I know this is not right. I could autowire subresource, but it needs
// to be request scoped and I get errors about proxying request scoped bean
// into singleton bean.
// I have also tried instantiating the subresource using ResourceContext
// but then Subresource's dependencies don't get injected
return new Subresource(id);
}
}
And another class
public class Subresource{
#Context
private UriInfo uriInfo;
#Autowired
private Dependency2 dependency2;
private String id;
public Subresource(String id){
}
#GET
public Response get(){
return Response.ok(id).build();
}
}
How do I get the spring managed dependencies to be auto injected in the sub resources? How does the sub resource get access to CXF managed dependencies?
I create factory bean to instantiate sub-resource:
public class SubResourceFactory {
#Autowired
private AutowireCapableBeanFactory autowireBeanFactory;
public SubResource createBean(String parameter1, Parameter2 parameter2) {
... creating SubResource instance, setting parameters to it
autowireBeanFactory.autowireBean(subResource);
return (SubResource) autowireBeanFactory.initializeBean(subResource, "subResource");
}
}
AutowireCapableBeanFactory allows to init bean created outside of Spring Context and inject any Spring beans to it.
SubResourceFactory is instantiated as Spring singleton bean in my project and injected in Root Resource, so i can use it like this:
#Resource
private SubResourceFactory subResourceFactory;
#Override
public SubResource getInfoFromSubResource(String parameter1) {
Parameter2 parameter2 = parameter2StoreService.getParameter2(parameter1);
return subResourceFactory.createBean(parameter1, parameter2);
}
But this subResource is managed only by Spring, so You can inject only Spring beans, You can not inject CXF-RS #Context beans.
There must be a way to do same thing to allow Spring and CXF-RS injections with ResourceContext, but I can see now, that it injects only CXF-RS beans, no Spring at all.

How do I use Apache Camel's Spring Remoting Proxy with XML as the transport?

I am using Apache Camel's Spring Remoting, version 2.11.0. I have the following in my beans.xml:
<camel:camelContext id="camel-client">
<camel:dataFormats>
<camel:jaxb contextPath="path.to.my.jaxb.index"/>
</camel:dataFormats>
</camel:camelContext>
<camel:proxy
id="myProxy"
serviceInterface="path.to.my.service.MyService"
serviceUrl="jms:queue:myQueue" camelContextId="camel-client"/>
By default, camel:proxy uses object serialization, but I would like to use JAXB instead. Is this possible? I have this pattern working over JAXB with ProducerTemplate, but when I switch to using camel:proxy, I get a NotSerializableException.
The producer template is created via the camel:camelContext tag and is injected via Spring:
#ContextConfiguration(locations={"beans.xml"})
public class MyTest extends AbstractJunit4SpringContextTests {
#Autowired ProducerTemplate producerTemplate; // this comes from <camel:camelContext>
#Autowired MyService myService; // this comes from <camel:proxy>
#Test
public void testMyService() {
MyRequest myRequest = new MyRequest();
// This correctly performs the JAXB serialization
MyResponse response = producerTemplate.requestBody("jms:queue:myQueue", myRequest, MyResponse.class);
// This still does Object serialization (and fails accordingly)
response = myService.getResponse(myRequest);
}
}

Resources