Jersey and Google Guice integration - java

My question is: why do I need to create AbstractModule when doing JavaSE application and ServletModule while creating application that is deployed on some kind of servlet container like jetty or tomcat? What are the differences between them?
I need to integrate Jersey with Guice. Is it necessary to register presence of Guice for Jersey to use it somehow? Can't I just enable injections and do them everywhere I want (normal classes, filters, handlers, services, DAOs etc.)? And why can't I just configure guice like in JavaSE application, but instead need to use ServletModule?
As far as I see on web, there are many examples of using HK2 services by Guice and vice versa, so I can consider it as important? (necessary?)
Thanks

An AbstractModule is the basic building block of the bootstrap (configuration) phase of Guice. You always need one or more of that. On the other hand a ServletModule is an specialization which does some configuration for you given the fact that it is running in a servlet container.
From the Guice documentation:
This module sets up the request and session scopes, and provides a
place to configure your filters and servlets from.
About the Guice-Jersey integration you certainly need to set it up. It won't work out of the blue. Guice, as any other dependency injection framework, works when it has the control of building your objects. When in doubt ask yourself who creates the object.
With Jersey, and JAX-RS in general, who creates the objects? Not you, you just define them. The container creates them. The JAX-RS runtime. In your case, the Jersey runtime. And Jersey uses internally the HK2 dependency injection framework. So you need to bridge both those frameworks in order to inject a JAX-RS class you have defined with some Guice resources. Or the other way around! That is the reason why there is a HK2-guice bridge. So Jersey would build your objects using HK2 and HK2 will look up your resources also on Guice thanks to the bridge.
A simple example. I use this code to initialize a REST API where I want to inject Guice resources.
#ApplicationPath("api")
public class ApiRest extends ResourceConfig {
private static final Logger log = LoggerFactory.getLogger(ApiRest.class);
#Inject
public ApiRest(ServiceLocator serviceLocator, ServletContext servletContext) {
log.debug("Inicialitzant Jersey.");
packages("net.sargue.app.api");
GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
Injector injector = (Injector) servletContext.getAttribute(Injector.class.getName());
if (injector == null)
throw new RuntimeException("Guice Injector not found");
guiceBridge.bridgeGuiceInjector(injector);
}
}
Please note that the above example needs the ServletModule registered as it pulls the Guice injector from the ServletContext. Or you can just add the injector to the ServletContext somewhere else. Or just create the injector when initializing the REST API, it depends on your preferences and the application.

Related

Google Guice - declarative binding?

I am new to guice and my background is JakartaEE. So I have a conceptual question about the binding of beans.
As far as I understand, in Guice I have to implement my AbstractModule where I bind my concrete implementations. Than I am able to inject those classes into other classes. Which means, I need to programmatically bind everything in my Module.
In JakaratEE we have the CDI Container which automatically scans all jar files for CDI beans and binds them automatically. This means I can add an external .jar file with CDI beans or Obsever Beans that automatically can react on specific CDI Events of my main application, without the need to register a ActionHandler programmatically in my main application. I can just fire the CDI event and all Listeners in any existing Jar file will be triggered by the Jakarta CDI Container.
It looks to me that Guice is not providing such a mechanism? Or is there a similar way that I can extend the main application without the need to compile it with the specific extension?

How to use Jersey as JAX-RS implementation without web.xml?

I have read that from JavaEE 6 web.xml is optional.
So without web.xml, how can I tell the application server to use Jersey as the implementation for JAX-RS specification?
What #AlexNevidomsky wrote in his answer is correct, as far as how to implement the app configuration with no web.xml; you use an #ApplicationPath annotation on an Application subclass.
#ApplicationPath("/api")
public class AppConfig extends Application {}
For more information on deployment options, see the Jersey Docs: Chapter 4. Application Deployment and Runtime Environments
Or more commonly, with Jersey as implementation, we would extend ResourceConfig (which extends Application).
#ApplicationPath("api")
public class AppConfig extends ResourceConfig {
public AppConfig() {
packages("package.to.scan");
}
}
So how is this implemented...
First things first, not all Java EE servers use Jersey. Actually the only ones I know that use Jersey are Glassfish and WebLogic. JBoss uses Resteasy. Tom EE uses CXF. WebSphere uses Apache Wink. Those are the only ones I can think of.
So I guess the question is "How does the Server know how to load the JAX-RS application?"
Servlet 3.0 introduced the pluggability mechanism, which makes use of a ServletContainerInitializer. How it works is that when the Server/Servlet container is started, it scans jars for a META-INF/services folder with a file named javax.servlet.ServletContainerInitializer. This file should include one or more fully qualified names of implementations of the ServletContainerInitializer.
This interface has only one method
void onStartup(java.util.Set<java.lang.Class<?>> c, ServletContext ctx)
The Set<Class<?> will be a list of classes, fitting the criteria in the #HandlesTypes annotation on the ServletContainerInitializer implementation. If you look at Jersey's implementation
#HandlesTypes({ Path.class, Provider.class, Application.class, ApplicationPath.class })
public final class JerseyServletContainerInitializer
implements ServletContainerInitializer {
You should notice some familiar annotation classes, as well as the Application.class. All these classes matching the criteria, while scanning, are added to the Set passed to the onStartup method.
If you scan the rest of the source code, you will see all the registration being done with all of those classes.
Resteasy uses
#HandlesTypes({Application.class, Path.class, Provider.class})
public class ResteasyServletInitializer implements ServletContainerInitializer
I won't get into to others.
Some source you can look at...
JerseyServletContainerInitializer source code
ResteasyServletInitializer source code
JAX-RS specs
You don't have to specify anything in web.xml. Define an activator class:
#ApplicationPath("/rest")
public class _JaxRsActivator extends javax.ws.rs.core.Application {
static {
//Check some system init on REST init.
Config.initCheck();
}
}

What is the equivalent of `transport-guarantee` when I register a Servlet in a BundleActivator without using web.xml?

I am running Servlets in an OSGI environment, specifically, I use Karaf with Pax Web / Jetty.
I was happily using the BundleActivator to instantiate servlets and register them with the HttpService. What I like about it is that it gives me a very straightforward way to handle dependency injection by wiring up a ServiceTracker.
However, for some things I can only find documentation about how to set them up via the classical web.xml configuration. Specifically, I miss an equivalent for the transport-guarantee instruction, i. e. a way to tell the HttpService that on certain URLs, it should insist on HTTPS and redirect the client if necessary.
Alternatively, if I can use the web.xml descriptor file as usual, but still get a convenient and simple way to wire up the servlet to my OSGi services, I would be fine with that.
Right now I'd say it's a web.xml only feature. Might want to open a new Feature Request. Regarding Injection of OSGi services in Servlets. If you combine your application with Pax CDI you are able to inject OSGi services by CDI means.
#WebServlet(urlPatterns = "/myServlet")
public class MyServlet extends HttpServlet {
#Inject
#OsgiService
private AnotherService service;
...

How is Spring Container created?

I am studying for the Spring Core certification and I have following doubt about this question:
What is meant by “container” and how do you create one?
I know that the Spring container is at the core of the Spring Framework. The container will create the objects, wire them together, configure them, and manage their complete lifecycle from creation till destruction. The Spring container uses dependency injection (DI) to manage the components that make up an application. These objects are called Spring Beans which we will discuss in next chapter.
And I know that there exist 2 containers:
Spring BeanFactory Container: This is the simplest container providing basic support for DI and defined by the org.springframework.beans.factory.BeanFactory interface. The BeanFactory and related interfaces, such as BeanFactoryAware, InitializingBean, DisposableBean, are still present in Spring for the purposes of backward compatibility with the large number of third-party frameworks that integrate with Spring.
Spring ApplicationContext Container: This container adds more enterprise-specific functionality such as the ability to resolve textual messages from a properties file and the ability to publish application events to interested event listeners. This container is defined by the org.springframework.context.ApplicationContext interface.
Ok...this is pretty clear for me but what is the correct answer about How to create a container?
I think that it is automatically created by the Spring when it reads the configuration class or the XML configuration file.
Or not? What am I missing?
In short, "The Container" is a Spring instance in charge of managing the lifecycle of your beans.
To create one, basically, you should do something like
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/application-context.xml");
Remember replacing /application-context.xml by the file where you define your own Spring beans.
Take a look at http://www.springbyexample.org/examples/intro-to-ioc-creating-a-spring-application.html
You could also substitute the xml by a configuration class. On that case you should have something like this:
#Configuration
public class Myconfig{
#Bean
public MyBean myBean(){
return new MyBean();
}
}
For this, take a look at http://www.tutorialspoint.com/spring/spring_java_based_configuration.htm

Injecting EJB with #EJB or #Inject in the service layer for my REST web service?

I have created some EJB's, they are annotated with #Stateless. To use these EJB's in the other EJB's I am currently using the #EJBannotation. I have created another layer (over the service layer) for my REST web service (I am using JAX-RS) and I wonder if I should use #EJB or #Inject. I know these two are different things - and they probably live in different containers? If I use #Inject do I get the same EJB that I would have gotten with #EJB. Or do I get an EJB from the CDI container?
I also guess that by using #Inject I don't get all the EJB features that I would have gotten from #EJB?
#Inject supports the injection of EJBs. There is no functional difference, CDI is doing a lookup to find the object using the standard JNDI locations. The #EJB annotation has some additional capabilities, mostly around remoting or non standard JNDI locations that wouldn't be supported OOTB by #Inject
Intersting link about: http://www.oracle.com/technetwork/articles/java/cdi-javaee-bien-225152.html I didn't try by myself, but looks like #Inject more powerful than #EJB...

Categories