Dynamic autowire in /src/groovy - spring

I want to be able to include Services in my Groovy Classes in /src/groovy
I found a solution with :
myBean(MyBean) { bean ->
bean.autowire = 'byName'
}
But I dont want to make this entry in the resources.groovy for all Class, so is there a Solution to Autowire all classes in a specific folder?
I'm using grails 2.4.3

This seems to be similar to this question: Grails 2.x service injection in Groovy/src
What we use and is proposed there is to get the service via the application context:
import grails.util.Holders
...
def myService = Holders.grailsApplication.mainContext.getBean 'myService'
It's not completely auto-wired, but seems to be the best way to get services into src/groovy.
Edit: also works for Grails 3

You can make a class com.example.MyClass in src/groovy a Spring bean by adding the following to BuildConfig.groovy
grails.spring.bean.packages = ['com.example']
and annotating the class with #Component, e.g.
#Component
class MyClass {
#Value('${conf.apiVersion}')
String apiVersion
#Autowired
SomeService someService
}
As shown above, you can dependency-inject the class with the usual Spring annotations such as #Value and #Autowired. I find this a much more convenient way to register a Spring bean than modifying resources.groovy.

Related

Sping-boot configuration-properties and service layer injection

I'm new to spring dependency-injection and am reaching out to learn about best practices. I would like to know if its a good design philosophy to inject classes annotated with #ConfigurationProperties into service layer classes (annotated with #Service). Im trying to map properties in my application.yml to a config-class as follows -
#ConstructorBinding
#ConfigurationProperties(prefix = "application")
class ApplicationConfig(
val kafka: someDeeplyNestedType = SomeDeeplyNestedObj()
) {
// helper functions
}
I'm then injecting above config class in service layer as follows -
#Service
#EnableConfigurationProperties(ApplicationConfig::class)
class RestService(val config: ApplicationConfig) {
init {
// Reference config object
// Reference application.yml properties via config object.
}
}
I'm curious to know if I can improve upon my current implementation - not sure if its agreeable to pass configuration classes to service-layer classes. I'm also curious to know if theres any better approach to wiring ApplicationConfig without needing to use EnableConfigurationProperties annotation.
It is agreeable, documented, and probably "unrivaled" (only bounded by: "limitations" (no SpEL -> helper functions!?;)).
To work with #ConfigurationProperties beans, you can inject them in the same way as any other bean, as shown in the following example:
#Service
public class MyService {
private final SomeProperties properties;
...
The only problems can arise from the "deeply", not "owning" the (config) structure ...and possibliy from "helper functions".
But
The prefix = "application" "sounds" suspicious!
Note:
[Most - almost All] (official) spring* boot properties, are already "typesafe", and have their object/class representation in spring-boot-autoconfigure packages.
Please study that "typesafe chapter", but also gazing at PropertySource Abstraction.
There is no hard rule for this as in Spring Boot we can add #EnableConfigurationProperties at a class level with stereotype annotations.
As a part of good practices EnableConfigurationProperties or any configuration thing should be part of Configuration class of or main spring boot class so any developer can easily figure out those configuration instead of going any specific service class and then check.
In your case, yo can use #EnableConfigurationProperties annotation in conjunction with #SpringBootApplication annotation.

Spring Hibernate won't implement Repository Class from Interface

I have two separate projects. One project contains my Application logic and Controllers in org.patrick.application, and one separate project contains my Hibernate entities, Dao, and models in org.patrick.hibernate. My problem is that Spring will not instantiate a implementing class for my CrudRepository.
Here is my Application.java class annotations in my Application project:
package org.patrick.application;
#SpringBootApplication
#Configuration
#EnableAutoConfiguration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = { "org.patrick.hibernate" })
#EntityScan(basePackages = { "org.patrick.hibernate" })
#ComponentScan(basePackages = { "org.patrick.hibernate", "org.patrick.application" })
These annotations should scan my second Hibernate project for all of my Hibernate objects.
My Hibernate repository looks like this:
package org.patrick.hibernate;
#Repository
public interface PatrickDao extends CrudRepository<MyModel, Long>
This repository does not have a class implementation. I am expecting Spring to populate this implementation for me.
Now, inside of my application org.patrick.application, I am trying to use the Dao like so:
package org.patrick.application;
#Autowired
private PatrickDao patrickDao;
This is causing my Application project to fail to start because of the following error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean found for dependency [org.patrick.hibernate.PatrickDao]: expected at least 1 bean which qualifies as autowire candidate.
I know that the core problem is that Spring is not implementing this interface -
because if I provide my own PatrickDaoImpl in the org.patrick.hibernate package, then the Application project will start just fine. This confuses me because I have the proper annotations on my Application.java class, and yet the Repository cannot be implemented by Spring for some reason.
Is there anything further I need to do in order to get Spring to implement the class for my Repository interface? In previous testing, this behavior works if everything is under the same package.
I found the problem. For this particular Model, the definition looked as such:
package org.patrick.hibernate;
public class MyModel implements Serializable {}
This Model did not have the #Entity annotation. If this annotation is missing, then Spring will give no warnings as to why it cannot implement the repository interface. In my case, it simply threw the NoSuchBeanDefinitionException exception.
I updated my Model with the proper annotations:
package org.patrick.hibernate;
#Entity
public class MyModel implements Serializable {}

Possible to autowire imported utility classes in Spring?

I want to use data mappers, logger, transfromers, etc. in my Spring web projects. Is it possible to autowire an imported (jar) utility dependency, without wrapping it in some #Component or #Service class? Do we even want to do it that way, or should we just use a static reference?
If your utils, are based on not static methods, then this is simple:
If you use java based configuration, then just declare that util in an #Bean annotated method.
#Configuration
public class YourConfig {
#Bean
public YourUtil util(){
return new YourUtil ();
}
}
in xml it could been as simple as:
<bean id="util" class="org.example.YourUtil" />
The following is true, but it is not what was asked for:
There are at least two other ways to inject beans in instances that are not created (managed) by Spring:
(1) add #Configurable annotation to this class - this requires real AspectJ (compile-time or load-time -weaving)
#see Spring Reference Chapter 7.8.1 Using AspectJ to dependency inject domain objects with Spring
#see this answer of mine https://stackoverflow.com/a/7007572/280244 for a quick "guide" to enable the #Configurable support
(2) invoke SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
#see this question and its (two highes voted answers) for some ideas how to use
You can only #Autowire a bean managed by Spring. So you have to declare your instance through some configuration : a bean in an xml file, or a #Bean method in a java configuration.
#Component are just automatically discovered and registered in the spring context.

How to Autowire repository interface from a different package using Spring Boot?

I am new to Spring Boot and want to autowire a repository from a different package in a Rest Controller. It seems that when I place the interface and implementation in a different package the actual controller the autowire seems to fail.
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.acme.repository.RawDataRepository] found for dependency:..
Controller:
package com.acme.controller;
import com.acme.repository.RawDataRepository;
// imports removed!
#RestController
#EnableAutoConfiguration
#ComponentScan("com.acme")
public class DataCollectionController {
#Autowired
private RawDataRepository repository;
// code removed!
}
I have tried to use the #ComponentScan annotation but this gives no solution.
Any idea what i am missing? Whenever i put the interface into the package in which the controller resides then all goes well.
If you have Spring Data #Repositories in a different package you have to explicitly #EnableJpaRepositories (or replace "Jpa" with your own flavour). Boot takes it's defaults from the package containing the #EnableAutoConfiguration so it might work to just move that class as well.
You have to use following two annotations
#EnableJpaRepositories(basePackages = "package-name")
#EntityScan(basePackages = "package-name")
EnableJpaRepositories will enable repository if main class is in some different package.
You need to use EntityScan as well to point to package where you have your entity beans or else it will fail with 'Bean is not of managed type' error.
Spring Boot Provides annotations for enabling Repositories.
So whenever someone uses any Repository (it can be JPARepository , CassandraReposotory) it should be enabled in Application Class itself.
Example:
#EnableCassandraRepositories("package name")
#EnableJpaRepositories("package name")
After providing the above annotations, the container takes care of injecting beans for repositories as well.

get reference to spring bean from class in src/groovy

I'm writing a Grails plugin that defines a Spring bean in the plugin descriptor
def doWithSpring = {
myBean(MyBean)
}
I need to get a reference to this bean from another class in the plugin.
class Something {
def doIt() {
// I need to get a reference to myBean here. Is this the best way?
MyBean myBean = ApplicationHolder.application.mainContext.getBean('myBean')
}
}
Something is a class defined in src/groovy within the same plugin as the bean, but Something is not itself a spring bean. In Grails 1.3.7 is there a better way of achieving this than that shown above? I'm looking for a better way because I know the *Holder classes are deprecated in Grails 2.0
In Grails 2.x exists the Holders utility class to get the grailsApplication and the applicationContext.
In 1.3.7 I think the option is create your own holder, as described here.

Resources