Java Spring DI not working with Java Configuration - java

I'm new to Java Spring and trying to use Java configuration and inject a dependency into a class constructor. I want to use constructor injection because the class methods require the dependency. It isn't working for me.
Use case: Create a JSON string from a Java object and validate it before returning.
Class: FakeJsonBuilder
Dependency: JsonValidator
Main class: Per Spring documentation the #SpringBootApplication annotation is a convenience annotation that adds #Configuration, #EnableAutoConfiguration and #ComponentScan so I should be good to go as far as dependency injection is concerned.
#SpringBootApplication
public class MySpringApplication {
public static void main(String[] args){
// Register the class we use for Java based configuration
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.register(ApplicationConfiguration.class);
context.refresh();
SpringApplication.run(MySpringApplication .class, args);
}
}
Java configuration class:
#Configuration
public class ApplicationConfiguration {
#Bean
public JsonValidator jsonValidator(){
return new JsonValidatorImpl();
}
#Bean
public JsonBuilder(){
return new FakeJsonBuilder();
}
}
FakeJsonBuilder class:
public class FakeJsonBuilder implements JsonBuilder{
private static Log logger = LogFactory.getLog(FakeJsonBuilder.class);
private static JsonValidator jsonValidator;
// I need an empty constructor for the ApplicationConfiguration setup to work.
public MlrModelJsonBuilder(){};
#Autowired
public FakeJsonBuilder (JsonValidator jsonValidator){
this.jsonValidator = jsonValidator;
boolean validatorInjected = (jsonValidator != null);
logger.info("Validator injected: " + validatorInjected);
}
.......... More methods
The jsonValidator dependency is not being injected, i.e. the log message is Validator injected: false

Quoting Martin: Fowler http://martinfowler.com/articles/injection.html
"My long running default with objects is as much as possible, to create valid objects at construction time. This advice goes back to Kent Beck's Smalltalk Best Practice Patterns: Constructor Method and Constructor Parameter Method. Constructors with parameters give you a clear statement of what it means to create a valid object in an obvious place. If there's more than one way to do it, create multiple constructors that show the different combinations."
I come from a .NET background and use Ninject to inject my dependencies into the class constructor for the reasons Fowler gives. I quoted Fowler because of his credibility but you will find many sources providing the same argument, i.e. if the class methods require the dependency then it should be injected into the constructor. So here's how I figured how to do it with Java Spring (I revert to my C# syntax - forgive the transgression):
The configuration class
#Configuration
public class ApplicationConfiguration {
#Bean
public IJsonValidator jsonValidator(){
return new JsonValidator();
}
#Bean
public IJsonBuilder jsonBuilder(){
return new JsonBuilder(jsonValidator());
}
}
The class into which we inject the dependency
public class JsonBuilder implements IJsonBuilder {
private static IJsonValidator _jsonValidator;
// #Autowired // not needed per Sotirios. tested and verified
public JsonBuilder(IJsonValidator jsonValidator) {
_jsonValidator = jsonValidator;
}
public String getFoobar() {
// Returns false. jsonValidator was injected
boolean foo = (_jsonValidator == null);
return "Validator was injected: " + foo;
}
... more methods

Related

How to make a singleton by generic type with class argument in Spring?

Let's suppose I have a Wrapper with generic type:
#Component
#Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
public class Wrapper<T> {
private final Class<T> wrappedClass;
public Wrapper(Class<T> wrappedClass) {
this.wrappedClass = wrappedClass;
}
}
And I want to use this Wrapper with many classes (for example > 100). Is it possible to make Spring create singleton of wrapper for each generic type and pass generic class as parameter to constructor? For example, Spring must always inject the same instance of Wrapper<Foo>. If it is possible, please give example with java code configuration, but not with xml.
If I understood correctly you want to add beans of wrapper dynamically based on some criteria that some beans (like Foo / Bar) adhere to and some don't.
This is a kind of advanced stuff in spring, but in a nutshell you will have to implement a Bean Factory Post Processor that will be called automatically by spring during the startup.
This is a point where you could analyze the beans by iterating over all the "accessible" beans (like Foo / Bar and others) and for beans that should be wrapped you will create a bean definition of the wrapper, despite the fact that the wrapper itself is not a bean.
I've created a simple example to illustrate this. In my sample project I've put everything under package "wrappers":
#Wrappable
public class Foo {
}
#Wrappable
public class Bar {
}
public class ShouldNotBeWrapped {
}
Note that I've put an annotation #Wrappable - a custom annotation that will serve as a "differentiator" of what should be wrapped and what not. The processing of the annotation will be done in Bean Factory Post Processor.
The annotation is nothing special really, it should be acessible in runtime (spring is a runtime framework and be put on classes):
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface Wrappable {
}
The java config will add Foo, Bar, ShouldNotBeWrapped as beans and also Bean Factory Post Processor that I'll describe below:
#Configuration
public class WrappersJavaConfig {
#Bean
public Foo foo () {
return new Foo();
}
#Bean
public Bar bar () {
return new Bar();
}
#Bean
public ShouldNotBeWrapped shouldNotBeWrapped () {
return new ShouldNotBeWrapped();
}
#Bean
public WrappersEnrichmentBFPP wrappersEnrichmentBFPP () {
return new WrappersEnrichmentBFPP();
}
}
The Wrapper class itself for the sake of example has toString but it doesn't differ much from your wrapper presented in the question:
public class Wrapper<T> {
private T wrapped;
public Wrapper(T wrapped) {
this.wrapped = wrapped;
}
#Override
public String toString() {
return "Wrapper for" + wrapped;
}
}
And the Main class will list all the loaded beans and get their classes + call toString so that we could see that the wrappers are defined correctly:
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(WrappersJavaConfig.class);
String[] names = ctx.getBeanDefinitionNames();
for(String name : names) {
Object bean = ctx.getBean(name);
if(bean.getClass().getPackage().getName().startsWith("wrappers")) {
System.out.println(ctx.getBean(name).getClass() + " ==> " + ctx.getBean(name));
}
}
}
}
Sidenote, the "if" condition in the main method is because I don't want to print the beans that spring loads by itself (infra stuff, etc) - only my beans which all reside in package "wrappers" as I've mentioned above.
Now the BeanFactoryPostProcessor - is a regular bean in a sense that it gets registered in the java config and it looks like this (your implementation might be different but the idea is the same):
public class WrappersEnrichmentBFPP implements BeanFactoryPostProcessor {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] bddNames = beanFactory.getBeanDefinitionNames();
for(String bddName : bddNames) {
Object bean = beanFactory.getBean(bddName);
if(bean.getClass().isAnnotationPresent(Wrappable.class)) {
BeanDefinition wrappedBdd = BeanDefinitionBuilder.genericBeanDefinition(Wrapper.class)
.addConstructorArgReference(bddName)
.getBeanDefinition();
((BeanDefinitionRegistry)beanFactory).registerBeanDefinition("wrapperFor" + bddName, wrappedBdd);
}
}
}
}
So I'm getting all the beans one by one in for-each loop, then I'm asking whether the bean has an annotation "wrappable" on it in the if condition. If it has - it must be wrapped.
In this case I create an "artificial" bean definition for Wrapper and add a constuctor that will reference my bean that should be wrapped.
Then I register the bean definition by adding it to the application context.
Run the code above and you'll see the output similar to mine:
class wrappers.WrappersJavaConfig$$EnhancerBySpringCGLIB$$f88f147d ==> wrappers.WrappersJavaConfig$$EnhancerBySpringCGLIB$$f88f147d#1283bb96
class wrappers.Foo ==> wrappers.Foo#74f0ea28
class wrappers.Bar ==> wrappers.Bar#f6efaab
class wrappers.ShouldNotBeWrapped ==> wrappers.ShouldNotBeWrapped#3c19aaa5
class wrappers.WrappersEnrichmentBFPP ==> wrappers.WrappersEnrichmentBFPP#3349e9bb
class wrappers.Wrapper ==> Wrapper forwrappers.Foo#74f0ea28
class wrappers.Wrapper ==> Wrapper forwrappers.Bar#f6efaab
As you see, two last lines are lines that correspond to the wrapper beans created for the same instances of Foo and Bar but nothing was created for the ShouldNotBeWrapped bean
The APIs used are somewhat obscure and look outdated, but again its pretty advanced stuff and works at the level of spring container infra itself. Having said that, there are a lot of tutorials about BeanFactoryPostProcessor-s.
Since Using BFPPs is not a usual task, and although I've provided the solution, I don't see any real usage of it, wrappers can't be used "instead" of Foo or Bar classes, do not have their APIs, etc. Maybe you could explain why do you need wrappers over some beans. Usually people use Aspects/BeanPostProcessors (not BFPP but BPP) to wrap the class into dynamic proxy (cglib / java.lang.Proxy) and add an additional behavior, stuff like #Transactional, cache handling and so forth is implemented in spring with BeanPostProcessors, so consider checking this direction as well.
It is possible and in fact a feature in spring.
Spring can inject your dependency with the correct generic type.The following example is from spring documentation.
Suppose you have an interface
public interface Store<T>{...}
and two beans. One implements Store,one implemenets Store.
#Configuration
public class MyConfiguration {
#Bean
public StringStore stringStore() {
return new StringStore();
}
#Bean
public IntegerStore integerStore() {
return new IntegerStore();
}
}
You can declare the type with the correct type parameter and spring will inject the right bean for you.
#Autowired
private Store<String> s1; // <String> qualifier, injects the stringStore bean
#Autowired
private Store<Integer> s2; // <Integer> qualifier, injects the integerStore bean

customizable aspects in spring

I’d like to apply a customizable aspect on two different services (spring bean). My problem is how/where to set/define the pointcut expression. One normally defines the pointcut expression on a ‘dummy method’ or directly on the advice method. However that means the pointcut is static (not customizable).
I’d like to define the pointcut at the bean creation level to be able to create the same kind of advice for different targets. Ideally I’d like to do something like this:
#Aspect
public class ServiceAspect {
private static final Logger LOG = LoggerFactory.getLogger(ServiceAspect.class);
private final String discriminator;
// no advice defined here!!!
public ServiceAspect(String discriminator) { this.discriminator = discriminator; }
public Object around(ProceedingJoinPoint jp) throws Throwable {
LOG.info(discriminator + " called");
return jp.proceed();
}
}
#Configuration
#EnableAspectJAutoProxy
#PropertySource("classpath:application.properties")
public class ServiceConfiguration {
#Bean
public MyService service1() { return new MyServiceImpl(); }
#Bean
#Around("bean(service1)") // define the advice when bean is created
#ConditionalOnProperty("aspect1Enbaled")
public ServiceAspect aspect() {
return new ServiceAspect("Aspect-1");
}
#Bean
public YourService service2() { return new YourServiceImpl(); }
#Bean
#Around("bean(service2)") // define a different advice when bean is created
#ConditionalOnProperty("aspect2Enbaled")
public ServiceAspect aspect() {
return new ServiceAspect("Aspect-2");
}
}
Notice that the #Around annotation is on the definition of the bean. I can thus reuse the aspect for different target. Using the #ConditionalOnProperty, this would enable me to turn on/off individual aspect base on a property.
Can anyone help me with this? I suspect I’ll need to create some kind of factory but can’t seem to see how I can REPLACE an already defined bean (the service bean) with a proxy!

Inheritance with Spring Java Config uses different bean

The following example shows explicit wiring of dependencies using spring java config that results in a different bean being wired in while using and interface for a spring configuration class.
This seems like it shouldn't occur or at least give the normal warning that there are two beans as candidates for autowiring and it doesn't know which to select.
Any thoughts on this issue? My guess is there is no real name spacing between configuration classes as is implied by the syntax "this.iConfig.a()" Could this be considered a bug (if only for not warning about the 2 candidate beans)?
public class Main
{
public static void main( final String[] args )
{
final ApplicationContext context = new AnnotationConfigApplicationContext( IConfigImpl.class, ServiceConfig.class );
final Test test = context.getBean( Test.class );
System.out.println( test );
}
}
public class Test
{
private final String string;
public Test( final String param )
{
this.string = param;
}
public String toString()
{
return this.string;
}
}
#Configuration
public interface IConfig
{
#Bean
public String a();
}
#Configuration
public class IConfigImpl implements IConfig
{
#Bean
public String a()
{
return "GOOD String";
}
}
#Configuration
public class ServiceConfig
{
#Autowired
IConfig iConfig;
#Bean
Test test()
{
return new Test( this.iConfig.a() );
}
#Bean
String a()
{
return "BAD String";
}
}
In this case, I would expect to have "GOOD String" to be always be wired in the Test object, but flipping the order of IConfigImpl.class, ServiceConfig.class in the context loader changes which string is loaded.
Tested with Spring 4.0.7
EDIT: Further testing shows this has nothing to to with inherented configs. Same thing results if you drop the IConfig interface.
I believe this was a behavior of Spring for years.
If you redefine a bean, the one that is being loaded as last wins.
Another question would be how to control the order of bean loading when java configs are used. Check out this article http://www.java-allandsundry.com/2013/04/spring-beans-with-same-name-and.html which shows you how to do the ordering by using #Import of the other Spring java config.
The solution is actually simple - if you need to override a previously
defined bean(without say the flexibility of autowiring with a
different bean name), either use the XML bean configuration for both
the bean being overridden and the overriding bean or use the
#Configuration. XML bean configuration is the first example in this
entry, the one with #Configuration would be something like this:
#Configuration
public class Context1JavaConfig {
#Bean
public MemberService memberService() {
return new MemberSvcImpl1();
}
}
#Configuration
#Import(Context1JavaConfig.class)
public class Context2JavaConfig {
#Bean
public MemberService memberService() {
return new MemberSvcImpl2();
}
}
Stepan has mentioned the issue of order. The following is about your comment on their answer
Overriding beans of the same name makes sense, but in this case, I'm
specifically referencing the bean as specified in the iConfig
configuration. I would expect to get the one specified there.
In order to implement #Configuration and the caching of beans so that calls like
#Configuration
class Example {
#Bean
public UncaughtExceptionHandler uncaughtExceptionHandler() {
return (thread, throwable) -> System.out.println(thread + " => " + throwable.getMessage());
}
#Bean
#Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Thread newThread() {
Thread thread = new Thread();
thread.setUncaughtExceptionHandler(uncaughtExceptionHandler()); // <<<<<< allowing this
return thread;
}
}
Spring actually uses CGLIB to create a proxy subtype of the #Configuration annotated class. This proxy maintains a reference to the backing ApplicationContext and uses that to resolve a bean.
So the call in your example
return new Test(this.iConfig.a());
isn't really invoking IConfigImpl#a(). It invokes this code (as of 4.2) from the proxy interceptor. The code uses the corresponding Method to determine the target bean name and uses the ApplicationContext's BeanFactory to resolve the bean. Since the bean definition for a bean named a has already been overriden, that new bean definition gets used. That bean definition is using the ServiceConfig#a() method as its factory method.
This is described in the documentation, here
All #Configuration classes are subclassed at startup-time with CGLIB.
In the subclass, the child method checks the container first for any
cached (scoped) beans before it calls the parent method and creates a
new instance.
Could this be considered a bug [...]?
I don't believe so. The behavior is documented.

How can Spring instantiate cClasses with private constructors (singleton pattern) and objects from Factories?

I am studying for the Spring Core certification and I have the following doubt related how can Spring instantiate classes with private constructors (such as Singleton pattern) or how can instantiate objects from Factories (that are not the Spring context).
For example I have the following singleton factory:
public class AccountServiceSingleton implements AccountService {
private static AccountServiceSingleton inst = new AccountServiceSingleton();
private AccountServiceSingleton() { ... }
public static AccountService getInstance() {
// ...
return inst;
}
}
This is a singleton factory because it build a private static object builded with a private constructor and I have a public method to get this object.
So I think that the problem how can Spring build this object? depends on the fact that that the constructor is private so I can't do something like this in my Java configuration class
#Confguration
public class ApplicationConfig{
#Bean
public AccountServiceSingleton accountServiceSingleton(){
return new AccountServiceSingleton();
}
}
because I can't access to the private AccountServiceSingleton() constructor.
At the same time I can't use the equivalent XML configuration for the same reason.
Have I understand what is the problem or am I missing something?
I think that I am missing something because on the documentation I read that I can use the following 2 solutions for the previous problem:
Use a #Bean method in #Configuration class: so, reading it, I think that the previous Java configuration class work...but why?
XML factory-method attribute in the XML configuration, searching online I found that have to be something like this, but how can I use this to configure the previous AccountServiceSingleton bean in an XML configuration?
Tnx
It's really easy, and you can do it, too:
Constructor cxor = AccountServiceSingleton.class.getDeclaredConstructor();
cxor.setAccessible(true);
return cxor.newInstance();
I found the answer by myself still reading the documentation. I think that the right answer for the question is:
If I want to configure this class as a Spring bean:
public class AccountServiceSingleton implements AccountService {
private static AccountServiceSingleton inst = new AccountServiceSingleton();
private AccountServiceSingleton() { ... }
public static AccountService getInstance() {
// ...
return inst;
}
}
using the Java configuration I simply have to annotate the relative bean method using #Bean in the configuration class.
If I want configure the beans using the XML configuration I have to use the factory method attribute, something like it:
<bean id=“accountService” class=“com.acme.AccountServiceSingleton”
factory-method="getInstance" />
So it say that the getInstance() method will be call to obtain the singleton object from my singleton factory
How about doing like this:
#Confguration
public class ApplicationConfig{
#Bean
public AccountServiceSingleton accountServiceSingleton(){
return AccountServiceSingleton.getInstance();
}
}

Dependency Injection in simple java program using CDI

Do we always require a beans.xml for a dependency injection in a simple java program using only CDI,and do we need to construct a bean to get the objects injected???
Below are the codes for simple java project with dependency Injection::
Interface
public interface Hello
{
public void sayHello(String str);
}
class
public class HelloImpl1 implements Hello{
public void sayHello(String str){
System.out.println("Hello from 1st block")
}
}
class
public class HelloImpl2 implements hello{
public void sayHello(String str){
System.out.println("Hello from 2nd block")
}
}
Class
public CallingHello(){
#Inject
Hello hello;
public void callHello(){
hello.sayHello("Hey");
}
}
Class
public Test(){
public static void main(String[] args){
CallingHello hello=new CallingHello();
hello.callHello();
}
Thats all i am doing and while running the test class its throwing nullpointerexception,and i am making simple classes no bean in eclipse,m i going right??
You can use autowiring , in order to inject dependencies (and possibly apply post processors) to an object that is not part of the application context.
You can use java config class with factory methods to configure ApplicationContext:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class AppConfig {
#Bean(name="HelloImpl1")
public HelloImpl1 helloImpl1() {
return new HelloImpl1();
}
#Bean(name="HelloImpl2")
public HelloImpl1 helloImpl2() {
return new HelloImpl2();
}
}
And then to instantiate:
ApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfig.class);
HelloImpl1 helloImpl1= (HelloImpl1)ctx.getBean("HelloImpl1");
helloImpl1.sayHello("#?*")
If you are using Spring for the dependency injection, you always need a configuration file. But it does not need to be named beans.xml.
Yes the beans are injected in other beans.
Technically no you don't have use an XML file define your beans and inject dependencies. It depends on the type of ApplicationContext you use. But, for most practical applications you'll use one of the AbstractXMLContextApplication instances which will load an XML file to figure out the beans your app has declared. The name of that file doesn't have to be beans.xml. That's a convention used, but it you don't have to name it that. You can override which file it looks for when you constructor the implementation of AbstractXMLApplicationContext object.
All you need to do is construct the bean container, and it will load the beans, resolve the dependencies, and startup the program (if you are using init-method). Typically my Spring Container Java programs look like this:
ApplicationContext context = null;
try {
context = new FileSystemXmlApplicationContext( new String[] { file } );
// pause until we want to shutdown or after something happens.
System.in.readLine();
} finally {
context.close(); // remember to clean up!
}
And I let the init methods on the bean startup my application.

Categories

Resources