CXF SpringComponentScanServer usage - java

I want to configure CXF to auto-scan for resources, providers, features, and the lot. In my search I came across the SpringComponentScanServer, which sounds like something I need. Unfortunately, documentation about this class is virtually non-existent.
When you have classes annotated with #javax.ws.rs.ext.Provider, they get picked up by CXF as expected. When you have a feature annotated with org.apache.cxf.annotations.Provider, it will also get picked up by CXF.
But what if you have a third-party feature that does not have this annotation?
For example, the CXF LoggingFeature? You cannot, as far as I know, add an annotation to a class if you can't change it's source code.
I came up with the following, hideous, solution, but surely, there must be a better way to do this???
#Configuration
#Import(SpringComponentScanServer.class)
public class CxfConfig {
#Component
#Provider(Provider.Type.Feature)
static class MyLoggingFeature extends LoggingFeature {
}
}
Here, I basically extend the existing LoggingFeature, only to add the #Provider annotation.
I found the following example CXF JAXRS Spring Boot example, which does what I want with the Swagger2Feature. That works, but only starting from CXF 3.1.6, and only for the Swagger2Feature. Not for LoggingFeature.
So my question is: is there a less hideous way to add the LoggingFeature?

Related

Replace AbstractContainerRequestValueFactory in Jersey 2.26

Hi all I´m struggling migrating from Jersey 2.25 to 2.26 since, it has a break change in a internal class of the library AbstractContainerRequestValueFactory
They claim in the issue sections that since the package is internal it should not be used. But they dont offer a solution or workaround.
Any idea how can I replace the use of that class for something else to continue using the provide implementation as I´ve been doing so far?
class MyOwnFactory extends AbstractContainerRequestValueFactory[Future[Object]] {
override def provide: Future[Object] = getContainerRequest.getProperty(Constants.individual).asInstanceOf[Future[Object]]
}
The equivalent would be to use a Supplier and inject the ContainerRequest, as the Supplier replaces the HK2 Factory and all AbstractContainerRequestValueFactory is is an HK2 Factory that injects the Provider<ContainerRequest>. Just look at the source
See also:
Jersey 2.26: register #Inject in ResourceConfig bindFactory cannot convert Factory to Supplier
Registering a custom ValueParamProvider in Jersey 2.27

What is the proper place to register MessageBodyReader and MessageBodyWriter implementations?

I have implemented Javax WS RS API MessageBodyReader for com.ca.tas.crypto.cmp.client.GeneralPKIMessageJaxRsReader and MessageBodyWriter for org.bouncycastle.asn1.cmp.PKIMessage so that I can easily use the types in CMP over HTTP REST API. Now, to register the types I have created META-INF/services/javax.ws.rs.ext.Providers file and put the class names there. Everything works fine, I can do REST calls using the API, except:
IntelliJ IDEA (or one of the plugins I have installed into it) complains that
Registered extension should implement javax.ws.rs.ext.Providers
on the two lines in the file. Based on the resources I have found somewhere on the Internet I thought adding #Provider and #Produces("application/pkixcmp") annotations should be enough.
I have noticed that FasterXML Jackson has META-INF/services/javax.ws.rs.ext.MessageBodyReader and META-INF/services/javax.ws.rs.ext.MessageBodyWriter files and those seem to register a class that implements the interfaces as well.
So my questions are:
Is the IntelliJ IDEA correct or wrong to complain about me not implementing javax.ws.rs.ext.Providers?
What is the correct file to register the MessageBodyReader and MessageBodyWriter implementations?
What is the authoritative documentation that would enlighten me about this?
Is the IntelliJ IDEA correct or wrong to complain about me not implementing javax.ws.rs.ext.Providers?
The files in the META-INF/services are part of the way we can create extensible applications by making use of the ServiceLoader. How it works is that the filename should be the name of the contract and the contents of the file should be a list of implementations of that contract. The ServiceLoader will then see the file and collect all the implementations. So using the ServiceLoader, we could do
ServiceLoader<MessageBodyReader> readersLoader
= ServiceLoader.load(MessageBodyReader.class);
Based on the class passed to the load method, Java will search for the file
META-INF/services/javax.ws.rs.ext.MessageBodyReader
and look at the contents of that file to find all the implementations that it should load.
So based on that information, you can see that IntelliJ is correct in complaining, as your reader and writer do not correctly implement javax.ws.rs.ext.Providers.
One thing I should point out is that I don't think that the ServiceLoader class is used directly as it requires that the service implementations have no-arg constructors. But this is the exact pattern that is used in regards to the META services.
What is the correct file to register the MessageBodyReader and MessageBodyWriter implementations?
The use of META-INF/services files is not something that is a part of the JAX-RS specification. This is an implementation detail that will be specific to the JAX-RS implementation, though this pattern is used a lot. You will mostly see the files being used in reusable libraries, such as the Jackson library you mentioned1.
If the provider is going to be a part of our application, then there are more common ways in which to register it.
The #Provider annotation as you mentioned is a marker annotation to detect a provider class that should be registered. When scanning is enabled, the runtime scans for classes annotated with #Provider and then it will register them with the application.
When we talk about scanning, there are a couple different ways: classpath scanning and package scanning. Classpath scanning is enabled in a JAX-RS application by having an empty Application class that is annotated with #ApplicationPath.
#ApplicationPath("/api/*")
public class ApplicationConfig extends Application {}
This is enough to get a JAX-RS application configured2. Classpath scanning will be enabled, which will scan the entire classpath for all classes annotated with #Path and #Provider and register those classes.
Package scanning is something that is specific to the Jersey implementation. We could configure our application as such
#ApplicationPath("api")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
package("the.package.to.scan");
}
}
Here, we are telling Jersey to scan the the.package.to.scan package for #Path and #Provider classes to register with the application.
Another way to register our providers is to explicitly register them. In Application subclass, you would override getClasses() or getSingletons() to register them as a class or as an object, respectively.
#ApplicationPath("/api/*")
public class ApplicationConfig extends Application {
private final Set<Class<?>> classes = new HashSet<>();
private final Set<Object> singletons = new HashSet<>();
public ApplicationConfig() {
classes.add(MyMessageBodyReader.class);
singletons.add(new MyMessageBodyReader());
}
#Override
public Set<Class<?>> getClasses() {
return this.classes;
}
#Override
public Set<Object> getSingletons() {
return this.singletons;
}
}
Note that once you override either of these methods and return a non-empty set, the classpath scanning is automatically disabled, and you will need to register everything manually.
If you are using the Jersey implementation, there are also Jersey specific ways that we can explicitly register resources and providers. For more discussion on this, see What exactly is the ResourceConfig class in Jersey 2?.
Another way I can think to register providers is through the use of features. We can use the vanilla Feature or we can use a DynamicFeature.
With the Feature, we register the provider with the entire application
// We should register the feature with our application
public class MyFeature implements Feature {
#Override
public boolean configure(FeatureContext context) {
context.register(MyMessageBodyReader.class);
}
}
With a DynamicFeature we can selectively register a provider with specific resource methods or resource classes. See more in the Jersey docs for dynamic binding. It should be noted that dynamic binding is more used with filters and interceptors (which are also in the general sense of the term, providers) and not so much with entity providers (MessageBodyReader/Writers).
There may be other ways to register your providers, but the one mentioned above are the main ways that you will see it being done in an application.
What is the authoritative documentation that would enlighten me about this?
I'm not sure how much information about META-INF/service files in any documentation. But explicit registration and classpath scanning, you will probably find in the JAX-RS specification or Jersey documentation
1 - It should be noted that just because the file is there, it does not mean that it will be used. It is up to the JAX-RS implementation whether or not they care to use it. For Example, Jersey will not use it on MessageBodyReaders and writers.
2 - See How to use Jersey as JAX-RS implementation without web.xml?

How do I get my Jersey 2 Endpoints to eagerly initialize on startup?

I am porting some code from Jersey 1.x and my implementation of various Health Check endpoints relies on all the #Singleton endpoint resources being initialized at start up so as to be able to detect which checks to do.
In Jersey 2.0 - whatever I do I can't seem to get my resource endpoints to initialise at start up and they are only constructed+initialized when each one is accessed for the first time.
I guess I could initialise them myself in the Application class but I'd rather use the package scanning!
Does anyone have any idea if there is some config option that will tell Jersey 2 to eagerly initialise all resource endpoints that it finds during package scanning?
Or some HK2 annotation or trick?
"Or some HK2 annotation or trick?"
You can use HK2's Immediate Scope. Just annotate the resource class with #Immediate (which acts like #Singleton, so you can get rid of that), then enable the immediate scope on the ServiceLocator. An example:
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
...
#ApplicationPath("/rest")
public class JerseyApplication extends ResourceConfig {
#Inject
public JerseyApplication(ServiceLocator locator) {
ServiceLocatorUtilities.enableImmediateScope(locator);
packages("thepackages.to.scan");
}
}
UPDATE
Based on this related question, if you need to explicitly instantiate the ResourceConfig, as in the case of the linked question, you can create a Feature and register the feature, as seen in this answer
UPDATE 2
Please see related issue
UPDATE 3
Looks like Immediate scope memory leak issue previously linked to has been resolved in version 2.22.1

Hard-coded #RequestMapping URL in Spring MVC Controller

I'm studying Spring 3 and I'm using it in a simple web-application.
Now I'm implementing a Spring MVC Controller using annotations, and I'm wondering:
Is there any best practice using #RequestMapping annotation?
I mean: I've seen that usually the URL mapped in this annotation is hardcoded in the class...
Is there a way to pass the URL in a 'loosely coupled way' (to obtain a more reusable class)?
I know that there are some wild cards that can be used, but I think that isn't the solution... Am I wrong?
EDIT:
I add an example to better explain my doubt.
Suppose I want my controller to be triggered by a request to /foo/bar/baz/mypage.htm, in my controller the handler method will be annotated with #RequestMapping("/foo/bar/baz/mypage").
Now I decide to change the URL triggering my controller into /foo/bar/otherpage.htm, so i need to edit my class, put #RequestMapping("/foo/bar/otherpage") on my handler method, recompile the project and deploy it again.
It seems to me not so practical...
Currently annotated controllers aren't very configurable.
As far as I know, the only possible approach to this problem is to use alternative HandlerMappings in order to configure "base URLs" of controllers. For example, as follows:
// Note the absense of #Controller to prevent this controller
// from being discovered by DefaultAnnotationHandlerMapping
public class FooController {
#RequestMapping("/list") public String list(...) { ... }
#ReqeustMapping("/save") public String save(...) { ... }
}
.
<bean
class = "org.springframework.web.servlet.mvc.support.ControllerBeanNameHandlerMapping" />
<bean name = "/foo" class = "FooController" />
<bean name = "/bar" class = "FooController" />
In this example two instances of FooController handle /foo/list, /foo/save, /bar/list and /bar/save respectively.
The upcoming Spring 3.1 will have an improved Spring 3.1 architecture (Spring 3.1 M2: Spring MVC Enhancements) that seems to be more flexible, though I haven't checked it yet.
I think you are trying to solve the wrong problem. If you wanted to change the pages that matched a controller you'd need to change a file somewhere. Would you rather change the file with the related code underneath it, or would you rather work with some XML files that specifies the URL and the class, and then you have to worry about the file being in the right place during runtime?
As there should be almost no code in your controller anyway, you should think of your controllers as compilable configuration files. Also, if you are using a build system like Maven or Ant and not compiling individual files by hand using Javac then compilation time shouldn't be an issue. If it becomes one, it's probably time to split your project into sub-projects.
I think you should just embrace this and see that it is probably not the issue you think it is. Also, did you know that controllers can match to expressions and not just literal strings? That gives you some flexibility in your naming.
If you really want to, you could just fall back to the Spring 2.0 style XML configuration, but I don't think anyone would recommend that.
I think that is not a best practice, but have you tryed with #PathVariable annotations?
#RequestMapping(value="/path/{word}", method=RequestMethod.GET)
public ModelAndView myRestMethod(#PathVariable String word) {
...
}

Spring #Configuration and <context:component-scan />

I have a scenario configuring Spring Security on embedded Jetty which seems to be somewhat solved if I make use of JavaConfig to configure the Jetty server.
As a result, it's looking like JavaConfig rather than XML might be the better option for large chunks of the project. However, there are some niceties in the XML namespaces, like <context:component-scan /> which aren't readily available in a #Configuration setting.
I have discovered that ApplicationContextAware is honored for #Configuration classes, so the following is possible
#Configuration
public class FooConfig implements ApplicationContextAware {
#Override
public void setApplicationContext(ApplicationContext applicationContext) {
((AnnotationConfigApplicationContext) applicationContext).scan("org.example");
}
}
The alternative, which is documented, is to have the #Configuration class use an #ImportResource annotation and pull in an existing XML file:
#Configuration
#ImportResource("applicationContext-withComponentScan.xml")
public class BarConfig {}
I guess the question is "Is it bad form to abuse ApplicationContextAware in this way, or is it really not abuse"? Something just feels oddly dirty about the approach so I'd not be surprised if the Spring guys had covered this in some way or another that I've not spotted.
For the interested, the problem relates to scanning a Jersey setup with #Resource and #Provider classes that I'd rather not have to manually manage entries in a class/XML configuration.
Now that Spring 3.1 is ready and out, you can safely use #ComponentScan if you are on Spring 3.1. It's not only for Spring MVC as one of the outdated answers mentions. You can use it as follows:
#Configuration
#ComponentScan({"com.foo.bar", "org.foo.bar"})
public class AppConfig{ /** config code */ }
Here is the documentation http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/context/annotation/ComponentScan.html
Is it bad form to abuse ApplicationContextAware in this way, or is it really not abuse
Yes, this is bad form. If you're going to fetch things out of the context manually, you may as well not bother with dependency injection in the first place.
However, your second option (#ImportResource("applicationContext-withComponentScan.xml")) is a good one - this is current best practice when you want to use these XML macros in combination with annotation-style config.
A third option is to use the current milestone build of Spring 3.1, which adds a way of doing these things all in Java, using #Feature. This is not yet production-ready, though.
Check this link out as well. It is a bit more specific (for a web application) but it has a very nice code example for the scanning, specifically: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html
from that link:
#ComponentScan(basePackages = { "org.example"} )

Categories

Resources