How we can use non-Singleton servlet or handler in Guice, for example I want to create new instance for every request and immediately destroy it or give it to garbage collector after processing the request.
I dont want to keep ii in memory as singleton or reuse for other future requests.
I think probably somehow by using bind() function,
RGDS
You want to use RequestScope.
I typically use provider methods with scopes, so you would have code that looks like
public class FooModule extends AbstractModule {
#Override protected void configure() {
// set up bindings
}
#Provides
#RequestScoped
PerRequestObject providePerRequestObject() {
return new PerRequestObject(...);
}
}
Be sure to install ServletModule and setup the GuiceFilter or else this won't work!
Have you tried #SessionScoped?
Related
I have an application that uses Jersey/JAX-RS for web services (annotations, etc) and Guice to inject service implementations. I don't really like the way Guice works with servlets directly, I prefer the Jersey way, so I had to do a bit of fussing to get the service injections to work since Guice wouldn't be creating my servlet classes, and I didn't want to deal with the HK2-Guice bridge. I did this by creating a listener class (called Configuration) that sets up the injectors in static fields upon application startup and then manually effecting the injections in each servlet class by creating a parent class that all my servlets extend with a constructor that contains the following:
public MasterServlet() {
// in order for the Guice #Inject annotation to work, we have to create a constructor
// like this and call injectMembers(this) on all our injectors in it
Configuration.getMyServiceInjector().injectMembers(this);
Configuration.getDriverInjector().injectMembers(this);
}
I know it's kind of hacky, but this works just fine in my servlets. I can use the Guice #Inject annotations on my services and switch between named implementations and so on. The problem comes when I go to set up my unit tests. I'm using JerseyTest to do my tests, but running a test against my servlets results in a 500 error with Guice saying the following:
com.google.inject.ConfigurationException: Guice configuration errors:
1) No implementation for com.mycompany.MyService was bound.
while locating com.mycompany.MyService
for field at com.mycompany.servlet.TestGetServlet.service(TestGetServlet.java:21)
while locating com.mycompany.servlet.TestGetServlet
The test looks like this:
public class TestServletTest extends JerseyTest {
#Test
public void testServletFunctional() {
final String response = target("/testget").request().get(String.class);
assertEquals("get servlet functional", response);
}
#Before
public void setup() {
Configuration configuration = new Configuration();
configuration.contextInitialized(null);
}
#Override
protected Application configure() {
return new ResourceConfig(TestGetServlet.class);
}
}
You'll notice in the setup method I am manually creating my Configuration class since I can't rely on the test container (Grizzly) to create it (I get NullPointerExceptions without those two lines). More about this below.
And here's the servlet being tested:
#Path("/testget")
public class TestGetServlet extends MasterServlet {
#Inject
MyService service;
#GET
#Produces({"text/plain", MediaType.TEXT_PLAIN})
public String testGet() {
//service = Configuration.getServiceInjector().getInstance(MyService.class);
return "get servlet functional";
}
}
Notice the commented line in the testGet() method? If I do that instead and remove the #Inject annotation above, everything works fine, which indicates that Grizzly is not creating my servlets the way I expect.
I think what's happening is that Grizzly doesn't know about Guice. Everything seems to suggest that Grizzly isn't seeing the Configuration class, despite the fact that by putting it in my test's #Before method it seems to be at least available to the classes that use it (see: the commented line in the TestGetServlet class). I just don't know how to fix it.
I'm still trying to figure this out but in the meantime I switched from Guice to HK2, which took a bit of doing but I figured this might be helpful for anyone who runs into this problem in the future.
I consider this an answer because truthfully my attempt to bypass the Guice-HK2 bridge but still use Guice with Jersey might not have been the best idea.
Switching from Guice to HK2 takes a bit of doing and there's no comprehensive guide out there with all the answers. The dependencies are really fussy, for example. If you try to use Jersey 2.27 you may run into the famous
java.lang.IllegalStateException: InjectionManagerFactory not found
error. Jersey 2.27 is not backwards compatible with previous versions due to HK2 itself. I am still working on getting that all to work, but in the meantime I had to downgrade all my Jersey dependencies to 2.26-b06 to get HK2 working properly.
Jersey thankfully already implements a bunch of HK2 boilerplate, so all you need to get injection working is proper use of #Contract, #Service (see HK2 docs for those), and then two new classes that look like this:
public class MyHK2Binder extends AbstractBinder {
#Override
protected void configure() {
// my service here is a singleton, yours might not be, so just omit the call to in()
// also, the order here is switched from Guice! very subtle!
bind(MyServiceImpl.class).to(MyService.class).in(Singleton.class);
}
}
And this:
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
register(new MyHK2Binder());
packages(true, "com.mycompany");
}
}
Simple enough, but this only works for the application itself. The test container knows nothing about it, so you have to redo the Binder and ResourceConfig yourself in your test class, like this:
public class TestServletTest extends JerseyTest {
#Test
public void testServletFunctional() {
final String response = target("/testget").request().get(String.class);
assertEquals("get servlet functional", response);
}
#Before
public void setup() {
}
#Override
protected Application configure() {
return new TestServletBinder(TestGetServlet.class);
}
public class TestServletBinder extends ResourceConfig {
public TestServletBinder(Class registeree) {
super(registeree);
register(new MyHK2Binder());
packages(true, "com.mycompany");
}
}
}
Having to do this is actually fine because you can switch out the Binder for a test binder instead, in which you've bound your service to a mocked service instead or something. I haven't done that here but that's easy enough to do: replace new MyHK2Binder() in the call to register() with one that does a binding like this instead:
bind(MyTestServiceImpl.class).to(MyService.class).in(Singleton.class);
And voila. Very nice. Obviously you could achieve a similar result with Named bindings, but this works great and might even be simpler and more clear.
Hope this helps someone save the hours I spent screwing around to get this working.
Is there any way to provide a dynamic binding at runtime? AbstractBinder allows you to bind a factory but the class type has to be known at compile time.
Something to the effect of:
public class MyDynamicBinder implements DynamicBinder {
#Override
public boolean canBind(Class<?> someContract) {
return iCanBindThis(someContract);
}
#Override
public Object bind(Class<?> someContract) {
return getMyInstance(someContract);
}
}
hk2 is an extremely dynamic injection container. Unlike guice and CDI it can add services to its ServiceLocator at any time (if you have appropriate privilege). With the ServiceLocator (which is a service available anywhere you have any other hk2 service) then you can use the methods in ServiceLocatorUtilities like addClasses or addOneDescriptor in order to add whatever services you need at any time at all. You can also remove services at any time, but few people ever do that (unless you are writing a dynamic container of your own)
I want to use Guice to produce instances (actually singletons/single instances for the module/dependency injection context), but have some of the managed instances being wrapped in a proxy.
The idea behind this is to add a synchronization layer around a few items which deal with "one at a time" resources. The only solution I've come up with is to create two Injectors.
Given the code below,
public class ApplicationContext {
private Injector injector;
public <T> T get(Class<? extends T> cls) {
return injector.getInstance(cls);
}
public ApplicationContext() {
injector = Guice.createInjector(new Module() {
binder.bind(InterfaceOne.class).to(ImplementationOne.class);
binder.bind(InterfaceTwo.class).to(ImplementationTwo.class);
binder.bind(InterfaceThree.class).to(ImplementationThree.class);
});
}
}
}
where ImplementationThree depends on InterfaceTwo, and ImplementationTwo in turn depends on InterfaceOne.
What I want now, is that after ImplementationTwo is instantiated, I want to wrap it in a Proxy before it's injected into ImplementationThree. So:
I want to use Guice to have ImplementationOne being injected into ImplementationTwo
Before ImplementationTwo is injected into ImplementationThree, I want to wrap it.
What I'd love to see, is a Guice interceptor that is invoked after the instantiation and injection of dependencies, but before it's handed over to the injector context.
I could use a Provider for ImplementationTwo, but then I don't know how to get an instance of InterfaceOne from Guice.
The Provider method can also use injection. Try
#Inject #Provides
public InterfaceTwo provideInterfaceTwo(InterfaceOne i){
return InterfaceTwoImplementation
}
Why not use plain old Guice AOP support? Something like
#SynchronizedAccess
public void foo(...){
...
}
this way you can see just by looking at the code that there is something more to the method.
If you absolutely want to wrap things in a Proxy:
If you only have a few classes to proxy, then #acerberus suggestions works fine.
To automate, you can use a #afterInjection, part of Custom Injections, and reassign the field to your proxy using reflection.
I find it a bit archaic to program using locks while we have things like akka around but YMMV.
I have a webapp which requires the usage of Tomcat 7 web sockets.
In this webapp all standard Servlets (those extending javax.servlet.http.HttpServlet) work nicely (and correctly) with Google Guice. To make my Servlet work with Guice handlers I simply:
decorate the servlet with #Singleton
declare private Provider for MyHandler instance & generate a setter which is marked for injection
decorate the Servlet's constructor with #Inject
Example to demonstrate points above:
#Singleton
public class MyServlet extends HttpServlet {
private Provider<MyHandler> myHandler;
#Inject
MyServlet() {
}
#Override
protected void service(..) throws ServletException { ... }
#Inject
public void setMyHandler(Provider<MyHandler> myHandler) {
this.myHandler = myHandler;
}
...
}
How can one call the same Guice handler, above called myHandler from a WebSocketServlet?
I can't adopt the same style as in the standard servlet use case because, rather than having a Singleton servlet as in the case of the standard servlets, each WebSocket communication results in an instance extending MessageInbound; then the appropriate method that would call MyHandler is called from a method (e.g. onOpen or onClose) within the MessageInbound instance; not from a method within an HttpServlet instance as MyServlet above.
What did I try? I did try some (conceptually wrong) solutions such as calling the websocket-servlet's handlers from within the MessageInbound instance; that of course results in scoping problems lower down the Guice stack trace. What is the conceptually correct way of doing this?
Update after looking at GitHub example:
How you use Guice is just fine. Since there is just one particular usage of MessageInbound any sugar like with the AbstractGuiceWebSocketServlet is unnecessary. Provider chatLogHdlr and then doing manual construction is OK. But you lose AOP support. If that is needed you might want to do Assisted Inject. But for now this is fine.
On a side note, use construction injection instead of setter injection.
I saw immediately what is the problem. It is not Guice but rather how you use Guice-Persist. I didn't used GP a lot and still use the venerable Warp-persist. But I see 2 problems with how you use Guice-persist in your code:
You need to inject the PersistService to start Guice-Persist. It is explained in the WIKI e.g.
public class PocWebApp extends GuiceServletContextListener {
#Inject
PersistService ps;
#Override
protected Injector getInjector() {
Injector injector = Guice.createInjector(new ServletModule() {
#Override
protected void configureServlets() {
install(new JpaPersistModule("DesktopPU"));
serve("/socket/main/").with(MainSocket.class);
}
});
injector.injectMembers(this);
return injector;
}
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
super.contextInitialized(servletContextEvent);
ps.start();
}
}
The PersistFilter is useless as only the first time WebSocket will go trough filter but all subsequent communication will not go trough the filter. Using the txn just around #Transactional (Session-per-transaction) is the way to go.
Off-topic:
How many users do you intend to support? If this is going to be a hardcore chat server I'd use Netty instead but it is somewhat more involved. Googling found this:
http://comoyo.github.com/blog/2012/07/30/integrating-websockets-in-netty/
Original answer:
So this is a question about style?
WebSockets != Servlets. There is nothing wrong if they require a slightly different style. I'd even prefer to be reminded I am not dealing with vanilla servlets.
Some observations:
WebSocketServlet is nothing special. You can easily use it with Guice-Servlet. E.g.:
#Singleton
public class FooGuiceWebSocketServlet extends WebSocketServlet {...}
And then refernce it as
serve("/foo").with(FooGuiceWebSocketServlet.class);
Now, MessageInbound that is special as is all handled by Tomcat as you explained. The MessageInbound is WebSocket scoped. Now Guice has no idea about this scope and it might make sense to leave it that way.
For starters I'd make sure MessageInbound is created by Guice. Something along this lines:
#Singleton
public class ExampleWebSocketServlet extends AbstractGuiceWebSocketServlet {
#Override
public Class<? extends StreamInbound> serveWith() {
return Foo.class;
}
public static class Foo extends MessageInbound {
#Inject GuiceCreatedAndInjected bar;
#Override
protected void onBinaryMessage(ByteBuffer byteBuffer) throws IOException {
// do nothing
}
#Override
protected void onTextMessage(CharBuffer charBuffer) throws IOException {
// this getSwOutbonds() is not very friendly to testing
getWsOutbound().writeTextMessage(bar.echo(charBuffer));
}
}
}
Where
public abstract class AbstractGuiceWebSocketServlet extends WebSocketServlet {
#Inject Injector injector;
#Override
protected StreamInbound createWebSocketInbound(String subProtocol, HttpServletRequest request) {
return injector.getInstance(serveWith());
}
public abstract Class<? extends StreamInbound> serveWith();
}
You can go from here to higher abstractions and/or scopings as needed. I don't particularly like #getWsOutbound() as it hinders testing.
Just keep on improving the style until you are satisfied. Say if you need more help (will modify answer).
I didn't quite understand what you're trying to accomplish. I would look for AOP support in Guice. It seems that you need that MyHandler is set (inject) before being used in some methods of MessageInbound subclass' instance. An aspect could do that.
However, there is one question you need to ask: where is the (instantialization) control? If there's some way to add some kind of delegation in your Tomcat application configuration, Guice could "enhance" the MessageInbound instances which, in turn, would have the proper MyHandler set before use.
I have a Play 2 application which is using Guice to inject a static object (a realtime sensor monitoring object) into Application.java:
controllers.Application:
public class Application extends Controller {
#Inject static MonitorService monitorService;
...
}
module.Dependencies:
public class Dependencies {
....
#Provides
#Singleton
public MonitorService getMonitorService(final MonitorFactory factory) {
return new MonitorService(factory){
#Override
public MonitorService(Factory factory){
return factory.getMonitor();
}
}
}
}
My problem is that I would like to access the factory or monitor object when the play application is exiting in order to shut it down gracefully. I have looked at hooking into the GlobalSettings.onStop but cannot see a way to extract a reference from the Play.Application object. I have tried injecting MonitorService into the Global class but it returns a null object so I am assuming the Dependencies object has been destroyed by this stage.
I am also aware this approach may be totally wrong ;)
Any help is greatly appreciated.
I assume that you are using the Typesafe plugin.
AFAIK, unfortunately, there is no listener when the plugin is shut down, there is an onStart() method, but not any onStop() method.
So either you fork the plugin, either you integrate Guice yourself in the onStart/onStop methods of the Global object.