Reputation: 33
I am creating a new plugin containing CustomService which is intended to replace an existing service from an existing plugin. Following the pattern found in custom security implementations and shown here, I've added the configuration to the resources.groovy, oldService(path.to.new.CustomService). I've also tried adding all injected classes into the closure for this service. (Actual service names are RegistrationPersonRegistrationCompositeService and NewRegistrationPersonRegistrationCompositeService in code block)
I dont want the original application code to have any reference to the new plugin. However, BuildConfig at the application level will require plugin.location entry. My resource.groovy mods are in the new plugin. I have not had success in this endeavor. Am I modifying the wrong resources.groovy? If this change is required in the original application code, I've lost the ability to leave the original code unaltered. I'm not extending the original Service nor using override annotation. My intent is to replace the service (Spring bean) on start-up. The new plugin has a dependency on the old plugin in an attempt to manage order of operations in loading these classes.
Does it matter that the old service is previously injected in a controller? this would require me to override the controller in the new plugin in the same fashion and inject the correct service for desired behavior?
I've found documentation showing that within a plugin, the resources.groovy will be ignored. Also, building the resources.groovy into a war is problematic. I have not found a solution. I'm getting no error that I can share, just that the desired behavior is missing; the original service is handling the requests.
//was resource.groovy - now renamed to serviceOverRide.groovy - still located in \grails-app\conf\spring of plugin
//tried this with and without the BeanBuilder. Theory: I'm missing the autowire somehow
import org.springframework.context.ApplicationContext
import grails.spring.BeanBuilder
def bb = new BeanBuilder()
bb.beans {
registrationPersonRegistrationCompositeService(path.to.services.registration.NewRegistrationPersonRegistrationCompositeService) { bean ->
bean.autowire = true
registrationRestrictionCompositeService = ref("registrationRestrictionCompositeService")
registrationPersonTermVerificationService = ref("registrationPersonTermVerificationService")
}
classRegistrationController(path.to.services.registration.ClassRegistrationController) { bean ->
bean.autowire = true
selfServiceLookupService = ref("selfServiceLookupService")
registrationPersonRegistrationCompositeService = ref("registrationPersonRegistrationCompositeService")
}
}
ApplicationContext appContext = bb.createApplicationContext()
Additional information: Added the following lines to the PluginGrailsPlugin.groovy. The original service is still handling these requests
def dependsOn = ['appPersonRegistration': '1.0.20 > *']
List loadAfter = ['appPersonRegistration']
def doWithSpring = {
registrationPersonCourseRegistrationCompositeService(path.to.new.registration.TccRegistrationPersonCourseRegistrationCompositeService)
}
def doWithApplicationContext = { applicationContext ->
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL)
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory()
beanFactory.registerBeanDefinition("registrationPersonCourseRegistrationCompositeService", BeanDefinitionBuilder.rootBeanDefinition(TccRegistrationPersonCourseRegistrationCompositeService.class.getName()).getBeanDefinition())
}
Upvotes: 0
Views: 1147
Reputation: 33
In this implementation, I had a utility method in a service for which I was attempting to provide an override. Problem is, the Aspect works as a proxy and must override a method that is called directly from another class. In my classRegistrationController, I was calling service processRegistration() which in turn called applyRules(). Example-only method names used. Since the service was calling its own utility, there was no opportunity for the proxy/wrapper to circumvent the call to applyRules(). Once this was discovered, I refactored the code in this fashion: Controller calls processRegistration as it always had. After returning, another call is made to the service, processLocalRules(). The new method is an empty placeholder intended to be overridden by the client's custom logic. The plugin with Aspect works now using resources.groovy. I prefer the doWithSpring as Joshua explained for this reason: my intent to get the plugin to work without modification to the original app-config; otherwise resource.groovy is a valid approach. Upvoting Joshua's answer as it does satisfy the requirement and is cleaner. Thanks!
Upvotes: 0
Reputation: 24776
I highly recommend you read the section of the documentation on Plugins. The reason why I recommend this is because plugins:
resources.groovy
doWithSpring
to effect the spring applicationFollowing the information in the documentation you should have no issue overriding the service in the application context.
You must implement your changes to the application context using doWithSpring
this is the key to solving your issues.
Upvotes: 1