|
I'd like to inject a service into a groovy src file I have. Dependency injection doesn't work here, so no
def myService If I use def myService = new myService() then I don't have the right context in the service, and DI doesn't work in there either. Is there another way? |
|
I think there are several ways to do this.
We do something like the following: def appContext = ServletContextHolder.servletContext .getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT) def myService = appContext.myService -Lee Wexler -----Original Message----- From: chrisbin [mailto:[hidden email]] Sent: Tuesday, August 10, 2010 1:13 PM To: [hidden email] Subject: [grails-user] Injecting services into src I'd like to inject a service into a groovy src file I have. Dependency injection doesn't work here, so no def myService If I use def myService = new myService() then I don't have the right context in the service, and DI doesn't work in there either. Is there another way? -- View this message in context: http://grails.1312388.n4.nabble.com/Injecting-services-into-src-tp2320133p2320133.html Sent from the Grails - user mailing list archive at Nabble.com. --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email -- _________________________________________________________ This communication is intended only for the addressee(s) and may contain confidential information. We do not waive any confidentiality by misdelivery. If you receive this communication in error, any use, dissemination, printing or copying is strictly prohibited; please destroy all electronic and paper copies and notify the sender immediately. --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
This is another thing I think Grails shoukd do without crazy imports or using Servlet classes normal people never heard about.
Grails should inject wherever is needed, period. 2010/8/10 Lee Wexler <[hidden email]> I think there are several ways to do this. -- Fernando da Motta Hildebrand IT Consultant Brooks' Law : "adding manpower to a late software project makes it later..." |
|
That would be a huge performance killer and add unnecessary complexity. You'd have to use AOP to monitor all object construction on the off chance that a src/groovy or src/java class has a dependency injection.
Burt p.s. "normal people" should read the FAQ :) http://grails.org/FAQ#Q:%20How%20do%20I%20get%20access%20to%20the%20application%20context%20from%20sources%20in%20src/groovy? Burt > This is another thing I think Grails shoukd do without crazy imports or > using Servlet classes normal people never heard about. > > Grails should inject wherever is needed, period. --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by chrisbin
chrisbin wrote:
> I'd like to inject a service into a groovy src file I have. Dependency > injection doesn't work here, so no > def myService > If I use > def myService = new myService() > then I don't have the right context in the service, and DI doesn't work in > there either. > > Is there another way? http://grails.1312388.n4.nabble.com/Using-autowiring-in-non-grails-components-td1366429.html If you are able to declare your Groovy class as a Spring bean rather than creating instances by calling the constructor then this is the easiest way to achieve what you're after. Ian -- Ian Roberts | Department of Computer Science [hidden email] | University of Sheffield, UK --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by burtbeckwith
Burt -
What about really strange people, who are still willing to do things the easy way ;) Roger On Aug 10, 2010, at 2:13 PM, Burt Beckwith wrote: > That would be a huge performance killer and add unnecessary complexity. You'd have to use AOP to monitor all object construction on the off chance that a src/groovy or src/java class has a dependency injection. > > Burt > > p.s. "normal people" should read the FAQ :) http://grails.org/FAQ#Q:%20How%20do%20I%20get%20access%20to%20the%20application%20context%20from%20sources%20in%20src/groovy? > > Burt > >> This is another thing I think Grails shoukd do without crazy imports or >> using Servlet classes normal people never heard about. >> >> Grails should inject wherever is needed, period. > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
Administrator
|
In reply to this post by fernando da Motta hildebrand
There is an easier way without doing imports. Just make your class a
Spring bean in resources.groovy: myBean(MyBean) { bean -> bean.autowire = true } Then you can reference your bean in controllers (it will be auto injected) def myBean And in your bean you can reference services and they will be injected class MyBean { MyService myService } No imports required Cheers Graeme On Tue, Aug 10, 2010 at 8:05 PM, Fernando da Motta Hildebrand <[hidden email]> wrote: > This is another thing I think Grails shoukd do without crazy imports or > using Servlet classes normal people never heard about. > > Grails should inject wherever is needed, period. > > 2010/8/10 Lee Wexler <[hidden email]> >> >> I think there are several ways to do this. >> >> We do something like the following: >> >> def appContext = ServletContextHolder.servletContext >> >> .getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT) >> def myService = appContext.myService >> >> -Lee Wexler >> >> >> -----Original Message----- >> From: chrisbin [mailto:[hidden email]] >> Sent: Tuesday, August 10, 2010 1:13 PM >> To: [hidden email] >> Subject: [grails-user] Injecting services into src >> >> >> I'd like to inject a service into a groovy src file I have. Dependency >> injection doesn't work here, so no >> def myService >> If I use >> def myService = new myService() >> then I don't have the right context in the service, and DI doesn't work in >> there either. >> >> Is there another way? >> >> -- >> View this message in context: >> http://grails.1312388.n4.nabble.com/Injecting-services-into-src-tp2320133p2320133.html >> Sent from the Grails - user mailing list archive at Nabble.com. >> >> --------------------------------------------------------------------- >> To unsubscribe from this list, please visit: >> >> http://xircles.codehaus.org/manage_email >> >> >> -- >> >> _________________________________________________________ >> >> This communication is intended only for the addressee(s) and may contain >> confidential information. We do not waive any confidentiality by >> misdelivery. If you receive this communication in error, any use, >> dissemination, printing or copying is strictly prohibited; please destroy >> all electronic and paper copies and notify the sender immediately. >> >> --------------------------------------------------------------------- >> To unsubscribe from this list, please visit: >> >> http://xircles.codehaus.org/manage_email >> >> > > > > -- > Fernando da Motta Hildebrand > IT Consultant > Brooks' Law : "adding manpower to a late software project makes it > later..." > -- Graeme Rocher Grails Project Lead SpringSource - A Division of VMware http://www.springsource.com --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
So, being somewhat new to Grails and quite new to Spring & Java, this may be a bit of a noob question.
When I try to follow this suggestion so that I can inject a service into a src/java file, I get the following error on running the app: ERROR context.GrailsContextLoader - Error executing bootstraps: Error creating bean with name 'nameOfMyClass': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [package.foo.bar.nameOfMyClass]: No default constructor found; nested exception is java.lang.NoSuchMethodException: package.foo.bar.names.nameOfMyClass.<init>() In the resources.groovy file, I've put: bens = { ... nameOfMyClassBean(package.foo.bar.nameOfMyClass) {bean->bean.autowire=true} } What am I doing wrong? |
|
Since your class has at least one constructor with parameters, the compiler isn't auto-generating the default no-arg constructor. The syntax you're using will create a new instance with the default constructor and set values via setters. Change it to pass in the required constructor args:
beans = { ... nameOfMyClassBean(package.foo.bar.nameOfMyClass, "foo", false, 42) {bean->bean.autowire=true} } or add a no-arg constructor if that makes sense: Burt
|
|
Thanks, but success remains elusive.
I tried adding a no-arg constructor first. However, I would still get Cannot invoke method methodName() on null objectwhenever the constructor called the myService.methodName(). Failing that, I tried using the previous suggestion of calling to the application context, as documented <a href="http://grails.org/FAQ#Q: How do I get access to the application context from sources in src/groovy?">in the FAQ . So, in my src/java class, I added: import org.codehaus.groovy.grails.web.context.ServletContextHolder as SCH import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes as GA Then, within the main class I added def ctx = SCH.servletContext.getAttribute(GA.APPLICATION_CONTEXT) def MyService = ctx.package.MyService Then, within the constructor of that class I finally made a call to a method in that service: def variable = MyService.methodName(inputVariable) I even took a stab at using annotations as described in another thread, but that attempt was the most sophmoric, and most fraught with difficulty since I'm trying to make a call to the service within the constructor. Perhaps I'm ommitting or overlooking a significant detail, such as that this file is in src/java and not src/groovy, or that the class is contained in a different package from the service I want to call? And yes, as you can see above, I did try explicitly calling the package that the service is in.
|
|
You need to modify your object at boot time. So if your class looks as follows:
class MyLibUtils{ def myCustomService //Injected at boot time } You still need to declare your service in resources.groovy, but this time in Bootstrap you would do something like this:
class Bootstrap{ def grailsApplication def init = {servletContext-> MyLibUtils.metaClass.myCustomService = grailsApplicaton.mainContext.getBean('myServiceAsDeclaredInResources')
} }
On Fri, Jul 27, 2012 at 2:08 PM, jonnybot <[hidden email]> wrote: Thanks, but success remains elusive. The Journey Is The Reward. |
|
In reply to this post by jonnybot
In your original code you showed your bean definition for the src/groovy class - using autowire should work. I'm guessing though (the absence of your code makes this all quite mysterious) that you're still creating new instances of your src/groovy class with "new ClassName()". That defeats the purpose of making it a Spring bean - you have to pull it from the application context in order for the bean definition to be used. You also need to make it prototype scope so each instance is new, and not just a reference to the singleton that's created by default if you don't specify the scope.
You're probably way better off not doing it this way. If src/groovy class is called from an artifact (a service, controller, etc.) just pass the Spring beans it needs to the methods that use them: class SomeController { def someService def someAction() { def thing = new Thing() // your src/groovy class thing.methodName(someService, 42) ... } } Burt
|
|
So, I really appreciate Roberto's answer. That said, I am inclined to agree with Burt that it may be wiser to just implement this at the controller level.
The java class in question is a wrapper used by our authentication system to retrieve roles based on the application you're using. I wanted to add a global role to this of student or employee (I work at a state university). We have a service method to retrieve that information from the database, but I wanted to stick it in the authentication layer so that the role would be assigned then. On reflection, it is much more straightforward to just call the service method from the controller when necessary. I wanted to avoid doing that for re-usability, but after thinking more deeply about it I'm convinced that calling the service from the controller as needed is just as reusable as getting the role in the controller would be. Thanks for helping me puzzle this one out. |
|
-So, once more, with feeling.
After abandoning this idea originally, I'm revisiting it. This time I'm going to try to give a bit more detail so we can actually talk about the best way to solve the problem. At the University where I work, one of my colleagues developed a plugin for Grails that we use for our in-house applications. It handles several different things, two in particular that I'm trying to work with: authentication and access to our Oracle database. Authentication We have an AuthenticationWrapper class in src\java that implements org.springframework.security.core.Authentication. Anywhere else in our applications where you would normally use the Authentication class (in our case, in our global_config.groovy file), we reference the AuthenticationWrapper class instead, which has methods for accessing things from the Authentication class. You might wonder, why are we doing this? The answer is that we have some domain classes in the plugin that define some custom roles and memberships on a per-application basis. This lets us designate certain users as "admins" for a given app, for example. The AuthenticationWrapper class finds those roles and puts them in the Authentication.authorities. Database Additionally there's a service class that has some methods that query our database for certain bits of info. In this case, the service method I want to use finds out if a person is an employee, a student, both, or neither, and just returns a plain ol' string after executing some groovy sql. I'd really like to use that method to define a generic role that we can then use in all of our applications (like, "Global_student" and "Global_employee"), so that each app doesn't have to call that service method from its own controllers. The problem LWexler's example (first reply to the original post) simply doesn't work in my src\java file. This is the same method documented in the FAQ. http://grails.org/FAQ#Q: How can I access domain classes from sources in src/groovy? I can define the application context okay... def appContext = ServletContextHolder.servletContext.getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT) ...but when I try to define a service based on that, the resultant variable comes back null. def myService = appContext.myService //myService is null here I also tried specifying the package name, but still no dice. def myService = appContext.home.package.myService //myService is null here As a result, I can't call any method in the service without getting a null Pointer Exception. As near as I can tell, this is a far more straightforward method for what I'm trying to accomplish. There is the alternative method that Ian, Graeme, and Burt described, and which is also documented at http://grails.org/doc/latest/guide/services.html#usingServicesFromJava. That said, it requires significantly more wiring, and I'd like to get the method that relies on a couple of imports working if I can. I appreciate anything your grey cells can do for mine. :) Jonny
|
| Powered by Nabble | Edit this page |
