I have a demo class FooComponent which is autowired in FooService and accessed in its constructor.
FooComponent.class:
#Component("fooComponent")
public class FooComponent {
public String format() {
return "foo";
}
}
FooService.class:
#Component
public class FooService {
#Autowired
private FooComponent fooComponent;
public FooService() {
System.out.println("in foo service const=" + this.fooComponent);
}
String doTatti() {
return fooComponent.format();
}
}
MainApplication:
#SpringBootApplication
public class InterviewApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(InterviewApplication.class, args);
System.out.println(ctx.getBean(FooService.class).doTatti());
}
}
In this tutorial, author says In the above example, Spring looks for and injects fooFormatter when FooService is created. In my case, fooFormatter is fooComponent.
But everytime, in the constructor my autowired property is null. My assumption is that it is because FoOService has not completely initialized? Is this correct?
If my assumption is correct, then why does below code work?
#Autowired
public FooService(FooComponent fooComponent) {
System.out.println("in foo service const=" + fooComponent);
}
I know this is very basic and stupid question, but I need help in understanding it.
UPDATE:
One last query, is there a way to Autowire my FooService instance in MainApplication, instead of getting it from ApplicationContext?
Thank you in advance.
In Spring, a bean is instantiated before its properties are injected. That is:
Instantiate the bean first
Inject the properties
This is because spring uses setter methods of the instantiated bean in order to inject properties.
This is the reason you are getting NullPointerException.
Preferable and recommended option is to use constructor injection, not a property or setter injection. In additional, one of the ways to resolve this is to create constructor with parameter as you did.
The whole explanation you can check here:
https://dzone.com/articles/spring-accessing-injected
EDIT:
Beans should be managed by the container. If we want to use one of them, we should rely on dependency injection rather than a direct call to ApplicationContext.getBean().
See this post: Why is Spring's ApplicationContext.getBean considered bad?
You need to use constructor injection instead of setter injection.
one of the drawbacks of setter injection is that it does not ensures dependency Injection. You can not guarantee that certain dependency is injected or not, which means you may have an object with incomplete dependency. On the other hand, constructor Injection does not allow you to construct an object until your dependencies are ready.
for your first question, u r right. Also when u need an object in the constructor you have to use the constructor injection and not property injection with #autowired;
for your second one, u can use the #Autowired prop in the main, but usually in this case is better to do your logic in the override of the commandLineRunner interface as follow :
#Autowired
private FooService foo;
public static void main(String[] args) {
SpringApplication.run(InterviewApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
foo.doTatti();
...
}
Related
I've got a Factory class in Java with some methods which return some Java Bean. All of these Java Beans have some DAO object as fields which are injected with the annotation #EJB. However in every case these DAO are all Null, so I suppose I've a problem with EJB injection. I use WebLogic for deploy. Any suggestions to resolve the issue?
//Factory class
public class Factory extends AbstractFactory {
#Override
public InterfaceService getService() {
return new ClassBean();
}
}
//Bean class
#Stateless(mappedName = "ClassBean")
#LocalBean
public class ClassBean implements IBeanService {
#EJB(beanName = "ClassDAO")
private ClassDAO classDAO;
public List<String> getList() throws ExpectedModelException {
return classDAO.getStringList(); //this one throws NullPointerException
}
Never create Enterprise-Beans using new.
The creation, caching, deletion,... is done by the container.
You must declare ClassDao as #Stateless or #Singleton, ... and the container will create and find it, hopefully if the names are correct.
The Factory is not necessary.
I defined some interfaces with generic, and I have some classes injected in Spring context as Beans, could I dynamic create a manager bean to manage them, and it could be autowired in fields without any Bean def code of this manager?
I have tried FactoryBean way to implement it, but not worked, it couldn't transmit generic class info and the FactoryBean bean couldn't transmit any changable arguments.
I have tried BeanFactory way to implement it, when I getBeansOfType, these objects created without autowired, not worked...
Now I have a finally method which I think it's not very smart that is using ImportBeanDefinitionRegistrar and ClassPathBeanDefinitionScanner to scan all classes, then insert the manager's beanDefinition.
I'll be very appreciate if you supply any method, Thank you very much !
I want to implement it like this:
public interface Strategy<E extends BaseEnum>
{
public E getType();
}
public interface LoginStrategy extends Strategy<LoginType>
{
public LoginStrategy getType();
}
#Strategy
public class ALoginStrategy implements LoginStrategy
{
public getType()
{
return LoginType.OTP;
}
}
#Strategy
public class BLoginStrategy implements LoginStrategy
{
#Autowired
private UserMapper;
public getType()
{
return LoginType.PASSWORD;
}
}
public LoginServiceImpl implements LoginService
{
#Autowired
private StrategyManage<LoginType, LoginStrategy> strategyManager;
}
I want the strategyManager in LoginServiceImpl which is marked Autowired could be auto generated.
I also have a other question. It may be easier to explain what I want.
I have a model convertor implements a ModelConvertor interface, TL is lowerModel's class, TU is upperModel's class.
now there is a bean include code like this:
#Autowired
private ModelConvertor<UserPO, UserDO> userConvertor;
normally Spring frame would throw a Exception with a "no such bean" message, so I want to make this field could auto inject a value like this:
#Autowired
private ModelConvertor<UserPO, UserDO> userConvertor[ = new DefaultModelConvertor(UserPO.class, UserDO.class)];
How can I do to solve these problems, thanks a lot again!
I have resolved this problem, scan specific packages and dynamic generate beans to put on context.
I have following #Configuration class, in which I am declaring a #Bean that depends on an #Autowired list of beans. However, this list is not complete when I am accessing to it. All #Bean definitions been executed, except the one defined in the same class.
#Configuration
public class MyConfig {
#Autowired
List<RequiredBean> requiredBeans;
#Bean(name="ProblemHere")
public CustomObject customObject() {
log.info(requiredBeans.size()); // 1 (debugging, I can see is the one defined in "AnotherConfigClass")
}
#Bean(name="reqBeanInsideClass")
public RequiredBean reqBean() {
// this method does not get executed
return new RequiredBean();
}
}
Having other classes like;
#Configuration
public class AnotherConfigClass {
#Bean(name="ThisOneGetsExecuted")
public RequiredBean reqBean() {
// this gets executed, and therefore, added to the list
return new RequiredBean();
}
}
Probably, the easiest solution would be to add #DependsOn("reqBeanInsideClass").
However:
I wonder why it works for all #Beans defined in different classes, but not in this one.
I'm not really sure that's exactly like that, and I'm afraid later on, another #Bean does not get executed
I guess the correct approach should be something like
#DependsOn(List<RequiredBean>) // Obviously this does not work
How should I solve this?
Update
I have copied the exact same class twice, in order to see what would happen, so now I have also:
#Configuration
public class MyConfig2 {
#Autowired
List<RequiredBean> requiredBeans;
#Bean(name="ProblemHere2")
public CustomObject customObject() {
log.info(requiredBeans.size());
}
#Bean(name="reqBeanInsideClass2")
public RequiredBean reqBean() {
// this method does not get executed
return new RequiredBean();
}
}
Amazingly, by doing this, both #Beans methods (ProblemHere & ProblemHere2) are called before both reqBeanInsideClass and reqBeanInsideClass2 methods.
For some reason I guess, Springboot is able to recognize #Beans required for a class as long as they are defined in another class.
Does this sound logic to anyone?
Can you not utilize the array input for #DependsOn rather than passing singular value, since it accepts String[]? That would wait for all the beans that are explicitly declared in the array before initializing, though has to be defined manually.
#Configuration
public class MyConfig {
#Autowired
List<RequiredBean> requiredBeans;
#Bean(name="customObject")
#DependsOn({"reqBeanInsideClass", "thisOneGetsExecuted"})
public CustomObject customObject() {
log.info(requiredBeans.size());
}
#Bean(name="reqBeanInsideClass")
public RequiredBean reqBean() {
return new RequiredBean();
}
}
#Autowired list of beans will be same as a single bean of same type, it will contain all beans with that type or with that superclass via springs injection, the problem is the ordering of bean initialization is not controlled properly, #DependsOn with array bean input should resolve this!
Or
You can make CustomObject bean #Lazy, so it will be initialized only when it is used within the code after initialization is done. The bean must not be used within another non-lazy bean I think. Just call some logic where an #Autowired CustomObject is used, it should instantiate the bean at that moment, where the list will contain all possible RequiredBeans
#Lazy
#Bean(name="customObject")
public CustomObject customObject() {
log.info(requiredBeans.size());
}
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.
I am new to Guice and have done a lot of reading on this but I have not hand any success with this. I am basically creating a DAO and want to use Guice and the AssistedInjection. Effectively the end goal is create the Injected factory in other classes throughout the application.
Intended use in a actual class that would have the injection of the factory to then get classes from it
public class TestAllModelBootstrap {
#Inject private DAOFactory factory;
public TestAllModelBootstrap() {
}
#Test
public void testGettingDAO() {
Injector injector = Guice.createInjector(new HibernateDAOModule());
Token oToken = new OperTokenV1();
AccountingDAO accountingDAO = factory.create(oToken);
}
}
This is based on Guice-based code of:
public interface DAOFactory {
public AccountingDAO create(Token oTicket);
}
The concrete class has a constructor annoated
#Inject
public HibernateAccountingDAO(#Assisted Token oTicket) {
this.oTicket = oTicket;
}
And the actual Module:
#Override
protected void configure() {
install(new FactoryModuleBuilder()
.implement(AccountingDAO.class, HibernateAccountingDAO.class)
.build(DAOFactory.class));
bind(SessionFactoryInterface.class)
.toProvider(HibernateSessionProvider.class);
}
Each time I try to run this:
java.lang.NullPointerException -> indicating that the:
factory.create(oToken);
has factory as a null. In reading up on the problem I was lead to believe that the injection will not work like I am using it in the "test" class. It needs to be put in an "injected" class itself. But this doesn't work either - if I wrapper the Factory injection in another class and then try to use it, it doesn't work.
Any help would be appreciated...
TestAllModelBootstrap did not come from an Injector—JUnit created it instead—so Guice hasn't had a chance to inject it yet. Guice can only inject into objects that it creates via getInstance (and those objects' dependencies, recursively), or objects passed into injectMembers, or existing instances as requested using requestInjection.
You can manually get a factory instance:
factory = injector.getInstance(DAOFactory.class);
Or ask Guice to inject your members using injectMembers:
injector.injectMembers(this); // sets the #Inject factory field
Or use a tool like Guiceberry to inject your test cases across your app.