#Resource Injections in Weld SE - weld

I have a bean with #Resource-annotated field:
#ApplicationScoped
open class UtilProducer {
...
#Resource(lookup = "java:jboss/datasources/mj2")
private lateinit var dataSource: DataSource
...
And I want to make Weld inject something into this dataSource field.
I tried to add my own implementation of ResourceInjectionServices - a MyResourceInjectionServices, but it doesn't seemed that it tries even to instantiate my class
val weld = Weld()
.disableDiscovery()
.addPackages(true, UtilProducer::class.java)
.addPackages(true, CDIViewProvider::class.java)
.addBeanClass(MyResourceInjectionServices::class.java)
How should I configure Weld SE to inject #Resource-annotated fields?

Finally I've found in documentation that in such cases I need to subclass a Weld object. and override a createDeployment method:
public class MyWeld extends Weld {
protected Deployment createDeployment(ResourceLoader resourceLoader, CDI11Bootstrap bootstrap) {
return super.createDeployment(new MyResourceLoader(), bootstrap);
}
}
In my case in Kotlin in looks:
val weld = object : Weld() {
override fun createDeployment(resourceLoader: ResourceLoader?, bootstrap: CDI11Bootstrap?): Deployment {
val deployment = super.createDeployment(resourceLoader, bootstrap)
deployment.services.add(ResourceInjectionServices::class.java, MyResourceInjectionServices())
return deployment
}
}.apply {
disableDiscovery()
addPackages(true, UtilProducer::class.java)
addPackages(true, CDIViewProvider::class.java)
}

Related

Instantiate Hilt Worker for Instrumentation Testing?

I am having problem trying to initialize my WorkerGetData class for instrumentation testing. I have done the following:
removed the default work initializer in manifest file.
added configuration provider in the Application class.
called WorkManagerTestInitHelper in the Test file.
added kapt "androidx.hilt:hilt-compiler:1.0.0" to app module.
added kapt "com.google.dagger:hilt-compiler:2.42" to app module.
But still get the error java.lang.NoSuchMethodException: com.example.myproject.WorkerGetData.<init> [class android.content.Context, class androidx.work.WorkerParameters].
I am using work manager version 2.7.1.
Code
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
#HiltAndroidApp
class Application : android.app.Application(), Configuration.Provider {
#Inject
lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
override fun onCreate() {
super.onCreate()
}
}
#HiltWorker
class WorkerGetData #AssistedInject constructor(
val repository: MyRepository,
#Assisted val context: Context,
#Assisted workerParameters: WorkerParameters,
): CoroutineWorker(context, workerParameters) {
override suspend fun doWork(): Result {
val data = repository.getData()
return Result.success(data)
}
}
#Test
fun testGetDataWorker() {
val request = OneTimeWorkRequestBuilder<WorkerGetData>()
.build()
val workManager = WorkManager.getInstance(context)
workManager.enqueue(request).result.get() /*<-----------------------error here*/
val workInfo = workManager.getWorkInfoById(request.id).get()
assertThat(workInfo.state).isEqualTo(WorkInfo.State.SUCCEEDED)
}
There was a 6th item which I had forgot to do. I needed to create a WorkerFatory() so that Hilt could correctly inject WorkerGetData constructor. There is a great article from Pietro Maggi on how to do this:
https://medium.com/androiddevelopers/customizing-workmanager-with-dagger-1029688c0978

Bind list of objects using Guice + Kotlin

I'm writing a JavaFX application in Kotlin with the following controller definition:
class MainController {
#Inject private lateinit var componentDescriptors: List<ComponentDescriptor>
/* More code goes here */
}
I'm using Guice for Dependency management. And I'm trying to inject the list of class instances loaded via java.util.ServiceLoader. My problem is to define a binding that will inject the list of loaded object instances into the declared field. I tried annotation based provisioning:
internal class MyModule: AbstractModule() {
override fun configure() { }
#Provides #Singleton
fun bindComponentDescriptors(): List<ComponentDescriptor> =
ServiceLoader.load(ComponentDescriptor::class.java).toList()
}
and multibinding extension (switched List to Set in field definition of corse):
internal class MyModule: AbstractModule() {
override fun configure() {
val componentDescriptorBinder = Multibinder.newSetBinder(binder(), ComponentDescriptor::class.java)
ServiceLoader.load(ComponentDescriptor::class.java).forEach {
componentDescriptorBinder.addBinding().toInstance(it)
}
}
}
but both of these approaches leads to the same error:
No implementation for java.util.List<? extends simpleApp.ComponentDescriptor> was bound.
while locating java.util.List<? extends simpleApp.ComponentDescriptor>
for field at simpleApp.MainController.componentDescryptors(MainController.kt:6)
while locating simpleApp.MainController
1 error
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1042)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1001)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)
at com.gluonhq.ignite.guice.GuiceContext.getInstance(GuiceContext.java:46)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:929)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
... 12 more
I'm starting to suspect that it somehow related to Kotlin gerenic variance and Guice strict type checking. But I don't know how to declare the binding so Guice will know what to inject into this field.
Yes, it happens because of variance but there's a way to make it work.
class MainController {
#JvmSuppressWildcards
#Inject
private lateinit var componentDescriptors: List<ComponentDescriptor>
}
By default Kotlin generates List<? extends ComponentDescriptor> signature for the componentDescriptors field. The #JvmSuppressWildcards makes it generate a simple parameterized signature List<ComponentDescriptor>.
#Michael gives the correct answer and explanation. Here's an example of one strategy for unit testing a Set multibinding for those that like to test their modules:
class MyModuleTest {
#JvmSuppressWildcards
#Inject
private lateinit var myTypes: Set<MyType>
#Before fun before() {
val injector = Guice.createInjector(MyModule())
injector.injectMembers(this)
}
#Test fun multibindings() {
assertNotNull(myTypes)
assertTrue(myTypes.iterator().next() is MyType)
}
}
#Michael comment is working. If you want to do the injection in constructor, you need do something like
class MainController #Inject consturctor(
private var componentDescriptors: List<#JvmSuppressWildcards ComponentDescriptor>
) {}

Grails create a service from a factory

I would like to utilize a service written in Java in my Grails app using dependency injection. Creating it in Java without injection would look like this:
ServiceFactory.newInstance().getElementService()
I would like to use this in the same way services are injected for controllers, services, and jobs.
class ImportJob {
def elementService
...
}
I know this should go into resources.groovy and this is what I have so far:
serviceFactory(ServiceFactory) { bean ->
bean.factoryMethod = 'newInstance'
}
elementService(ElementService) {
}
I have found few resources in the documentation to help with this. How do I complete the elementService so it is creating the object as described above? Should I use a BeanBuilder?
You could create a FactoryBean for this since it's not as direct as calling a method in a class:
package com.mycompany
import org.springframework.beans.factory.FactoryBean
import org.springframework.beans.factory.InitializingBean
class ElementServiceFactoryBean implements FactoryBean<ElementService>, InitializingBean {
private ElementService elementService
ElementService getObject() { elementService }
Class<ElementService> getObjectType() { ElementService }
boolean isSingleton() { true }
void afterPropertiesSet() {
elementService = ServiceFactory.newInstance().elementService
}
}
and you'd register it in resources.groovy as
elementService(ElementServiceFactoryBean)
Use bean.factoryMethod and bean.factoryBean in the elementService bean.
serviceFactory(ServiceFactory) { bean ->
bean.factoryMethod = 'newInstance'
bean.scope = 'singleton'
}
elementService(ElementService) { bean ->
bean.factoryMethod = 'getElementService'
bean.factoryBean = 'serviceFactory'
}
This is a simple solution especially if ServiceFactory is external and cannot be changed.

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.

Grails - access static config object in codec class

I am currently updating my Grails project in order not to use the deprecated ConfigurationHolder class.
This goes fine in most cases, but I am facing trouble in my custom codec classes, where I have been using the following approach until now:
import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH
class MyCodec {
static boolean myStaticConfigProperty=CH.config.myStaticConfigProperty
static encode = { something ->
if(myStaticConfigProperty)
...
}
}
Direct injection using
def grailsApplication
does not work in this case since this will be injected as a non-static object.
Instead I have tried to use the approach suggested in this post getting-grails-2-0-0m1-config-info-in-domain-object-and-static-scope, but I cannot make it work even after injecting the grailsApplication object into my codec metaclasses in the bootstrap:
class BootStrap {
def grailsApplication
def init = { servletContext ->
for (cc in grailsApplication.codecClasses) {
cc.clazz.metaClass.getGrailsApplication = { -> grailsApplication }
cc.clazz.metaClass.static.getGrailsApplication = { -> grailsApplication }
}
}
}
Could anyone suggest an approach that will allow me to access the config object in a static way inside codec classes?
I'd suggest something like this completely untested code:
class MyCodec {
static def grailsConfig
static boolean myStaticConfigProperty = grailsConfig.myStaticConfigProperty
static encode = { something ->
if(myStaticConfigProperty)
...
}
}
class BootStrap {
def grailsApplication
def init = { servletContext ->
for (cc in grailsApplication.codecClasses) {
cc.grailsConfig = grailsApplication.config
}
}
}
If all of your codec classes just need the same one configuration property, you could skip injecting the grailsApplication and/or the config object entirely, and just set the one static property from BootStrap.
it works for me in grails 2.2.3
import grails.util.Holders as holders;
class MyFileCodec {
static encode = {file ->
def configPath= holders.grailsApplication.config.share.contextPath
return "${configPath}/${file.name}"
}
}
grails.util.Holders has been introduced since grails 2.0, it's the way to access config object.

Resources