JAX-RS #PathParam to inject in class member variable? - rest

I want to do something like this:
#Stateless
#Path("/sensors/{sensorid}/version")
#Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML})
#Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML})
public class SensorVersionRestView extends VersionRestView{
#PathParam("sensorid")
private String sensorid;
#GET
#Path("count")
// so the complete path is i.e.
// domain.com/rs/sensors/111211/version/count
public void getCount() {
// do something with the sensorId....
}
}
But the only thing I get is null on runtime (I use Glassfish v3 with Jersey). The compiler and eclipse never mentions a problem with the #PathParam at the member class variable.
What's wrong with my construct?
The main problem is, why I doesn't want to use the whole path on each method in this class, that there exists another class which handles some rest operations on the sensor layer (deomain.com/rs/sensors/count i.e.)

I believe you need to change it to this:
#Stateless
#Path("/sensors/{sensorid}/version")
public class SensorVersionRestView extends VersionRestView {
#GET
#Path("count")
#Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML})
#Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML})
// domain.com/rs/sensors/111211/version/count
public void getCount(#PathParam("sensorid") String sensorid) {
// do something with the sensorId....
}
}

Because injection occurs at object
creation time, use of this annotation
on resource class fields and bean
properties is only supported for the
default per-request resource class
lifecycle. Resource classes using
other lifecycles should only use this
annotation on resource method
parameters. - JSR-311 Javadocs
You should be able to annotate fields with #PathParam as long as the resource class lifecyle is per-request. By default the life-cycle of root resource classes is per-request.
EDIT: I don't think you can achieve this using EJBs. If you remove the #Stateless annotation, it should work.

Related

EclipseContext get beans of type

I have classes:
#Creatable
#Singleton
public class Sample1 implements ISample {
}
#Creatable
#Singleton
public class Sample2 implements ISample {
}
How can i get all beans of type ISample from EclipseContext?
The Eclipse context does not support anything like this. All you can do is look for objects with a specific name (or specific class which is just converted to a name).
Additionally objects declared using #Creatable are not even created and added to the context until something actually uses them.

Abstract components via org.osgi.service.component annotations

I am migrating from org.apache.felix.scr annotations to org.osgi.service.component annotations. I have a set of Components that inherit from a common abstract class. In the felix case, I can use a #Component annotation with the option componentAbstract=true on the super class, and then use #Reference annotation in the super class. I cannot find how to migrate this to osgi annotations.
Is it possible to use Component annotations in a super class of a Component? And if so, what is then the appropriate way to handle the properties and metatype generation?
So, what I am looking for, is something like this
/* No component definition should be generated for the parent, as it is
abstract and cannot be instantiated */
#Component(property="parent.property=parentValue")
public abstract class Parent {
#Reference
protected Service aService;
protected activate(Map<String,Object> props) {
System.out.println("I have my parent property: "+props.get("parent.property"));
#Override
public abstract void doSomething();
}
/* For this class, the proper Component definition should be generated, also
including the information coming from the annotations in the parent */
#Component(property="child.property=childValue")
public class Child extends Parent {
#Activate
public activate(Map<String,Object> props) {
super.activate(props);
System.out.println("I have my child property: "+props.get("child.property"));
}
public void doSomething() {
aService.doSomething();
}
}
By default BND will not process DS annotations in parent classes. You can change that with -dsannotations-options: inherit but please see http://enroute.osgi.org/faq/ds-inheritance.html why you shouldn't!
2021-02-23 UPDATE: It seems like the page mentioned above is no longer available. I don't know if it was moved elsewhere or simply removed but its content (in Markdown format) is still available on GitHub: https://github.com/osgi/osgi.enroute.site/blob/pre-R7/_faq/ds-inheritance.md

Spring AOP : Interface method with Parameter annotation captured, but annotation is not present

I'm using Spring AOP to intercept a method execution.
I have an interface that looks like the following:
public interface MyAwesomeService {
public Response doThings(int id, #AwesomeAnnotation SomeClass instance);
}
Here is the implementation of the interface:
public class MyAwesomeServiceImpl implements MyAwesomeService {
public Response doThings(int id, SomeClass instance) {
// do something.
}
}
Now i would like any method which has a parameter annotated with #AwesomeAnnotation should be captured by Spring AOP.
So I wrote the following aspect which works.
#Aspect
#Component
public class MyAwesomeAspect {
#Around("myPointcut()")
public Object doAwesomeStuff(final ProceedingJoinPoint proceedingJoinPoint) {
final MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();
// annotationMatrix is empty.
}
#Pointcut("execution(public * *(.., #package.AwesomeAnnotation (package.SomeClass), ..))")
public void myPointcut() {}
}
However when I try to find the parameter annotations I don't get any annotations back. As mentioned above, the annotationMatrix is empty.
So here are my questions:
Why is the annotationMatrix empty? Probably because parameter annotations are not inherited from an interface.
Why I'm able to capture the method execution. Since Spring AOP is able match the pointcut, Spring somehow is able to see the method's parameter annotations but when I try to see that using methodSignature.getMethod().getParameterAnnotations() it doesn't work.
I also faced this issue with one of my parameter annotations. I was able to fix the same by making sure that the parameter annotation definition had RetentionPolicy as RUNTIME and Target as PARAMETER
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PARAMETER)
public #interface Param {
public String name();
}
The answers to your questions:
Parameter annotations are not inherited from interfaces to implementing methods. In fact, annotations are almost never inherited, only from class (not interface!) to subclass if the annotation type itself is annotated by #Inherited, see JDK API documentation.
Update: Because I have answered this question several times before, I have just documented the problem and also a workaround in Emulate annotation inheritance for interfaces and methods with AspectJ.
Because during compile or weave time AspectJ can match your pointcut against the interface method and thus sees the annotation.
You can fix the situation by adding the annotation to the parameter in your interface implementation, e.g. like this:
#Override
public Response doThings(int id, #AwesomeAnnotation SomeClass instance) {
// ...
}
Then with an aspect like this...
#Aspect
#Component
public class MyAwesomeAspect {
#Pointcut("execution(public * *..MyAwesomeService.*(*, #*..AwesomeAnnotation (*), ..)) && args(*, instance, ..)")
static void myPointcut(SomeClass instance) {}
#Around("myPointcut(instance)")
public Object doAwesomeStuff(Object instance, ProceedingJoinPoint proceedingJoinPoint) {
System.out.println(proceedingJoinPoint);
System.out.println(" instance = " + instance);
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();
for (Annotation[] annotations : annotationMatrix) {
for (Annotation annotation : annotations) {
System.out.println(" annotation = " + annotation);
}
}
return proceedingJoinPoint.proceed();
}
}
... you get a console log similar to this:
execution(Response de.scrum_master.app.MyAwesomeServiceImpl.doThings(int, SomeClass))
instance = de.scrum_master.app.SomeClass#23fc625e
annotation = #de.scrum_master.app.AwesomeAnnotation()

CXF #CrossOriginResourceSharing Annotation

I am using CXF/Karaf, and I have many different RESTful resources within multiple packages/classes.
Question: Is there a way to avoid having to write annotations above every resource, such as #CrossOriginResourceSharing?
I would like to be able to put this in one place. Below is an example of how this is currently being used:
#CrossOriginResourceSharing(
allowOrigins = {"http://<ip>:<port>"}
)
#GET
#Path("/rest")
#Produces(MediaType.APPLICATION_JSON)
public String rest();
You can add this to the class instead of on each resource in the class (and I haven't tested this but you could possible create a super class with this annotation and extend it but I'm not sure if CXF will honour it):
#CrossOriginResourceSharing(
allowOrigins = {"http://<ip>:<port>"}
)
public class resourceGroup {
#GET
#Path("/rest")
#Produces(MediaType.APPLICATION_JSON)
public String rest();
}

guice ignores providers?

It seems Guice is ignoring my #Provider methods of my module.
I have a class MyModule like this:
public class MyModule extends AbstractModule {
protected void configure() {
bindInterceptor(Matchers.any(), Matchers.annotatedWith(Timed.class), new GuiceEnabledLoggingInterceptor());
bind(OneClass.class).to(OneClassImpl.class);
// And more binding lines...
}
#Provides
public AnotherClassInApi provideMyClass() {
return AnotherClassInApi.getInstance();
}
// And more #Provides methods
}
Main method is
public static void main(String[] args){
ConfigHandler.getInstance().loadConfigWhenNotRunningInsideMicrocontainer();
Injector INJECTOR = Guice.createInjector(new MyModule());
// ...
}
In some other part of the project I have class AnotherClassInApi, which is a very standard singleton plus one method:
public class AnotherClassInApi {
private static final AnotherClassInApi INSTANCE = new AnotherClassInApi();
private AnotherClassInApi() { }
// ... more methods
public static AnotherClassInApi getInstance() {
return INSTANCE;
}
}
Well, I understand that should effectively bind any request for an AnotherClassInApi object to the getInstance() method, but it doesn't work. Funny thing, a breakpoint in the #Provide method is never reached while debugging, but one in the configure method is reached. It seems guice is ignoring my provider annotation, and I think I'm following exactly what Guice guide says about #Provider, so I'm already stuck.
I've been googling around, but can't find anything similar. Any help will be much appreciated.
Thanks!
The concept of Providers (and #Provides methods) is, that they are only called when actually needed. So unless you really use your Injector to create an instance that has an #Inject dependency, your Provider is not ignored, just not used (nor needed).
You can monitor all configured bindings by using "injector.getAllBindings()".
java.util.Map,Binding> getAllBindings()
Returns a snapshot
of this injector's bindings, both explicit and just-in-time. The
returned map is immutable; it contains only the bindings that were
present when getAllBindings() was invoked. Just-in-time bindings are
only present if they have been requested at least once. Subsequent
calls may return a map with additional just-in-time bindings. The
returned map does not include bindings inherited from a parent
injector, should one exist.
This method is part of the Guice SPI and is intended for use by tools
and extensions.