When writing a startupbean (#Singleton #Startup #PostConstruct) is there anyway for me to get the ServletContext? - startup

So I am trying to create a task that fires off at regular intervals and I want it to get some things from the ServletContext:
...
#Singleton
#Startup
public class InitTimers {
#Resource
private TimerService timerService;
#PostConstruct
public void initTimer() {
...
// I want ServletContext here, how do I?
ServletContext context = getServletContext();
...
}
#Timeout
public void timeout(Timer timer) {
...
}
}
Can an EJB 3.1 #Startup #Singleton access the ServletContext?

No, this is not possible. I recommend moving the logic to a ServletContextListener contextInitialized method, and then call the singleton to do startup work as required.

Related

Can't inject the guice dependency in the jersey filter

In the process of setup a bridge between guice and jersey, I ran into one problem.
When trying to create a jersey filter, I was unable to inject guice dependencies into it.
I found a duplicate, however there is no solution to the problem there.
Everything is exactly the same.
The only difference is that I don't get a startup error. The filter works, but my dependencies are null.
Interestingly, Filter and HttpFilter work fine. But it doesn't really work for me.
There's another thing that's interesting. In the resource, which I understand is an HK2 dependency, I can inject guice bean.
#ApplicationPath("/test")
private static class TestApplicationConfig extends ResourceConfig
{
public TestApplicationConfig()
{
register(JacksonFeature.class);
register(AuthFilter.class);
register(new ContainerLifecycleListener()
{
public void onStartup(Container container)
{
ServletContainer servletContainer = (ServletContainer) container;
ServiceLocator serviceLocator = container.getApplicationHandler().getServiceLocator();
GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
Injector injector = (Injector) servletContainer
.getServletContext()
.getAttribute(Injector.class.getName());
guiceBridge.bridgeGuiceInjector(injector);
}
public void onReload(Container container)
{
}
public void onShutdown(Container container)
{
}
});
}
}
In ServletModule child.
serve(path).with(ServletContainer.class, ImmutableMap.of(
"javax.ws.rs.Application", TestApplicationConfig.class.getName(),
"jersey.config.server.provider.packages", sb.toString()));
I trying with register(AuthFilter.class) and #Provider
#Singleton
#Provider
public class AuthFilter implements ContainerRequestFilter
{
#Inject
private SomeInjectedService someInjectedService; **// null here**
#Context
private ResourceInfo resourceInfo;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
// some code
}
}
SomeInjectedService I register by guice
bind(SomeInjectedService.class).asEagerSingleton();
Where can I start diagnosing and what can I do?
UPD:
I noticed different behavior when using different annotations.
If I use javax.inject.Inject, I get the following error message.
org.glassfish.hk2.api.MultiException: A MultiException has 3 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=SomeInjectedService,parent=AuthFilter,qualifiers={},position=-1,optional=false,self=false,unqualified=null,1496814489)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of some.package.AuthFilter errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on some.package.AuthFilter
If com.google.inject.Inject, just null. As I understand this method is not correct.
Considering that javax Inject is trying to inject the service but can't find it. Can we conclude that the bridge is not working correctly? But if it's not working correctly, why can I inject this service into my resource?
#Path("/test")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class SomeResource
{
private final SomeInjectedService someInjectedResource;
#Inject // here I use javax annotation and this code working correctry
public SomeResource(SomeInjectedService someInjectedResource)
{
this.someInjectedResource = someInjectedResource;
}
#GET
#Path("/{user}")
public Response returnSomeResponse(#PathParam("user") String user) throws Exception
{
// some code
}
}

Jersey 2 per-request #Context injection

Overview
In Jersey 2, can I inject a custom, request-specific value into my resource? Specifically, I would like to inject a MyThing which can be derived from my custom security context MySecurityContext. I would like to inject MyThing directly to make the code clean.
Is there any way to do this? According to this question it can't be done using a ContextResolver although this article and this example suggest it might be possible.
What Works
Using an auth filter, I am able to set my custom security context using code like this:
#Provider
public class HttpTokenAuthFilter implements IComposableJaxRsAuthFilter {
#Override
public boolean doAuth(ContainerRequestContext requestContext) throws WebApplicationException {
// error handling omitted
requestContext.setSecurityContext(MySecurityContext.fromHeaders(requestContext));
}
}
... and then in my resource I can pull a value from it:
#Path("/foo")
public class MyResource {
#Context
private SecurityContext securityContext;
#Get
public String doGetFoo() {
MyThing myThing = ((MySecurityContext)securityContext).getThing();
// use myThing to produce a result
}
Where I'm Stuck
... however, since this is going to be repeated a lot, I would much rather just write:
#Context
private MyThing myThing;
I tried defining a ContextResolver. I see it getting constructed, but I never see it getting invoked, so I have not yet tried any of the techniques linked above. Is this even the correct class to be using?
#Provider
public class MyThingResolver implements ContextResolver<MyThing> {
public MyThingResolver() {
System.out.println("ctor");
}
#Override
public MyThing getContext(Class type) {
System.out.println("getContext");
if (type.equals(MyThing.class)) {
return new MyThing(); // TODO: SHOULD ACTUALLY USE CURRENT MySession
}
return null;
}
}
Almost the solution
Per this answer and the refinements specified at this followup, it's almost possible to accomplish the injection using a Factory. The only caveat is, you must inject MyThing via a Provider, otherwise it's going to get created (with the default SecurityContext) before the filter runs and swaps in the MySecurityContext.
The factory code looks like this:
public class MyThingFactory implements Factory<MyThing> {
#Context
private SecurityContext securityContext;
#Override
public MyThing provide() {
return ((MySecurityContext)securityContext).getThing();
}
#Override
public void dispose(MyThing session) {
}
}
The resource can then inject it like this:
#Context
private Provider<MyThing> myThingProvider;
... and consume it like this:
MyThing myThing = myThingProvider.get();
// use myThing
The factory registration in the AbstractBinder looks like this:
this.bindFactory(MyThingFactory.class) //
.to(MyThing.class) //
.in(RequestScoped.class);
(Edit) Proxies to the Rescue!
Per the comment from #peeskillet, it is possible to get rid of the Provider by proxying MyThing. (Per # jwells131313, MyThing must therefore be an interface or a proxy-able class.)
The binding then looks like this:
this.bindFactory(MyThingFactory.class) //
.to(MyThing.class) //
.proxy(true) //
.in(RequestScoped.class);
and injection finally works as desired:
#Context
private MyThing myThing;

Grails - Bootstrap - null pointers instead of services

I'd like to use data generator at init in my application. It works fine when create objects using .save() method, but it doesn't work when I want to use dedicated services, because of null pointers instead of injected services. That's my code:
I have defined DataGenerator bean inside conf/spring
beans = {
dataGenerator(DataGenerator)
}
My Bootstrap.groovy looks like:
class BootStrap {
def dataGenerator
def init = { servletContext ->
dataGenerator.generateData()
}
}
In `DataGenerator' I have:
class DataGenerator{
BookService bookService
def generateData() {
log.info("Generating books")
createBooks()
}
def createBooks(){
(1..40).each() {
CreateBookCommand command = new CreateBookCommand()
/* some command populate code*/
bookService.create(command);
}
}
}
The problem is, that I cannot invoke create() method, because bookService is always null
BookService is simple grails service with some dependencies, of course placed in grails-app/services
class BookService {
UserService userService
SpringSecurityService springSecurityService
def create(CreateBookCommand command){
Book book = new Book()
command.bindTo(book)
book.save(flush:true, failOnError:true)
}
/*some other methods*/
}
Could you tell me how to fix it?
Try this in resources.groovy
beans = {
dataGenerator(DataGenerator) { bean ->
bean.autowire = 'byName'
}
}
I assume DataGenrator being a class outside the grails artifact (that is: placed in src/groovy), you can refer the already available service class in the context as:
beans = {
dataGenerator(DataGenerator){
bookService = ref('bookService')
}
}
or try autowiring byName as mentioned by #sudhir.

Play 2.1 with Guice 3.0 - Access not available outside Controller classes

Am trying to learn how guice plays with Play 2.1 framework. I have a service to which I need access outside the service package. I have placed the below in Global file
protected Injector configure() {
injector = Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
bind(MyService.class).to(MyServiceImpl.class).in(Singleton.class);
}
});
return injector;
}
#Override
public <A> A getControllerInstance(Class<A> clazz) throws Exception {
return injector.getInstance(clazz);
}
Inside the controller class am able to get to my object by doing below and everything seems to be fine
#Inject
MyService serviceObj
But elsewhere outside the controller the same object appears to be null. For example I have a core module which takes care of talking to the service. The controller classes hands out the job to the core module. I need to be able to get hold of this MyService obj in the core module classes.
What am I missing here guys?
Thanks
Karthik
I had figured a way out to do this.
In my configure method I had to use this
protected Injector configure() {
injector = Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
requestStaticInjection(TheClassThatNeedsMyService.class);
}
});
return injector;
}
And in my TheClassThatNeedsMyService I had to just do
#Inject MyService serviceObj;
Just for reference this is how my Service class looks like
#ImplementedBy(MyServiceImpl.class)
public interface MyService{
...
}
#Singleton
public class MyServiceImpl implements MyService{
...
}
Now am able to get access to my service object whereever I want in my application. Hope it helps someone
Thanks
Karthik
As an alternative to static injection, see the play-guice sample here:
http://typesafe.com/activator/template/play-guice
Guice can be used in a conventional manner with Play.

Grails unit tests: Accessing defined beans via grailsApplication

I have some (non-Grails-artifact) classes that access the service layer beans via passing around the grailsApplication object. However I'm having trouble unit testing the classes implemented in this way. Why doesn't the bean get registered in the main context?
#TestMixin(GrailsUnitTestMixin)
class ExampleTests {
void setUp() {}
void tearDown() {}
void testSomething() {
defineBeans {
myService(MyService)
}
assert grailsApplication.mainContext.getBean("myService") != null
}
}
The above code fails with:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myService' is defined
What I'm trying to do is access services from plain old Java classes via the grailsApplication. This works, but not in unit test environment. Should I do it differently?
class POJO {
MyService myService;
public POJO(GrailsApplication grailsApplication) {
myService = (MyService) grailsApplication.getMainContext().getBean("myService");
}
}
The answer is that in the GrailsUnitTestMixin the applicationContext that holds your beans is set as the parentContext in the grailsApplication
beans.registerBeans(applicationContext)
static void initGrailsApplication() {
...
//the setApplicationContext in DefaultGrailsApplication set's the parentContext
grailsApplication.applicationContext = applicationContext
}
So you can get your beans with:
defineBeans {
myService(MyService)
}
assert applicationContext.getBean("myService")
assert grailsApplication.parentContext.getBean("myService")
EDIT
Today I faced the same problem, and my solution is:
#Before
void setup() {
Holders.grailsApplication.mainContext.registerMockBean("myService", new MyService())
}
In my case (grails 2.4.4) the accepted solution didn't work but pointed me in the right direction, this line worked instead as the bean factory in the mainContext within my unit test was an OptimizedAutowireCapableBeanFactory
Holders.grailsApplication.mainContext.beanFactory.registerSingleton('myBean', new MyBeanClass())
I have spent some time with the same issue, in my case running grails 2.2.4 and having (in src/groovy):
import grails.util.Holders
class SomeClass {
transient myService = Holders.grailsApplication.mainContext.getBean 'myService'
.....
}
Which is a bit different to question author, but at least it will be useful for someone coming from search engine results
Nevertheless accepted answer did not work for me, so I came up with a bit different approach of mocking and registering service used in SomeClass.
import grails.util.Holders
.. other imports
#TestMixin(GrailsUnitTestMixin)
class SomeClassTests {
#Before
void setUp() {
Holders.grailsApplication = grailsApplication
defineBeans {
myService(MyServiceMock)
}
}
....
}
class MyServiceMock extends MyService {
// overriden methods here
}

Resources