I have a spring core application. In which I have private constructors. while executing the application, it throws
java.lang.IllegalStateException: Cannot load configuration class
at the time of bean creation.
I searched over I found that, could be problem because of AOP, but I am not using AOP. What would be the problem.
private Demo() {
//private constructor.
}
You should make a public constructor in order spring framework can instantiate the bean, the other way you can do it is doing a public static factory method, but you will need to say to the spring framework, what uses this method in order to instantiate this bean.
Related
I have a Quarkus application that works in batch mode. I have a QuarkusMain class, with a method that implements QuarkusApplication interface.
That method is a static method, so I'm not able to inject Beans because they have a null value.
What is the way to inject Beans in Quarkus from a static method in a QuarkusMain class?
Thanks.
Are you really after creating beans in the static method, or more just after how to startup Quarkus ?
In main method the only thing you need to do is call Quarkus.run(YourMain.class, args); which then will make YourMain class a bean and in here allow #Inject.
You can also use picocli which also ends up with a class you can use #Inject.
Example of that I have here: https://github.com/jbangdev/jbang-catalog/blob/master/catalog2readme.java
You can use Arc class in this way:
Annotate your beans with a #Startup annotation.
https://quarkus.io/guides/lifecycle#startup_annotation
Then, in your static method:
YourBean yourBean = Arc.container().instance(YourBean.class).get();
I have a Wicket panel in which I want to inject bean using #SpringBean
public class SomePanel extends Panel {
#SpringBean
private BlogSummaryMailGenerator blogSummaryMailGenerator;
}
But this BlogSummaryMailGenerator has injection via constructor defined like this:
#Component
public class BlogSummaryMailGenerator {
private BlogRepository blogRepository;
private BlogPostRepository blogPostRepository;
#Autowired
public BlogSummaryMailGenerator(BlogRepository blogRepository,
BlogPostRepository blogPostRepository) {
this.blogRepository = blogRepository;
this.blogPostRepository = blogPostRepository;
}
}
And when SomePanel is instantiated I am getting an exception
Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at net.sf.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:721) ~[cglib-3.1.jar:na]
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:499) ~[cglib-3.1.jar:na]
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) ~[cglib-3.1.jar:na]
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216) ~[cglib-3.1.jar:na]
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377) ~[cglib-3.1.jar:na]
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285) ~[cglib-3.1.jar:na]
at org.apache.wicket.proxy.LazyInitProxyFactory.createProxy(LazyInitProxyFactory.java:191) ~[wicket-ioc-7.2.0.jar:7.2.0]
Adding empty no-args constructor to the BlogSummaryMailGenerator solves this issue but adding such code only to make injection work is wrong and I would like to avoid it.
Any suggestions how to make #SpringBean work with beans using injection via constructor?
The real problem is in CGLIB. It requires a default constructor to be able to create the proxy instance. The real Spring bean is created separately by Spring and has no such restrictions. The default constructor needed by CGLIB could be even private as far as I remember.
Update: Since Wicket 9.5.0 Wicket could also use ByteBuddy instead of CGLib.
Another solution is to use an interface for this bean. Then Wicket will use JDK Proxy instead of CGLIB and in this case there is no need of default constructor in the implementation.
Solution
To be able to take advantage of constructor injection for #SpringBean in Wicket components you just have to add Objenesis to your compile time dependencies.
Explanation
Objenesis is a little and less known byte code manipulation library which (in opposite to CGLIB provided together with Wicket) is able to create a proxy object for a class which has no default (no args) constructor. If you add it as a compile dependency to your project then Wicket will switch it's internal lazily initializable proxy creation logic to take advantage of Objenesis (instead CGLIB which requires no args constructor) while instantiating a proxy. Unfortunately this feature is not documented but I can confirm it works in my case.
The error message is pretty clear. Wicked trying to create instance of proxy class for BlogSummaryMailGenerator with CGLIB library. Since you didn't (or you can't) provide arguments to constructor, it looking for contstructor with no arguments. But it can't, and you get error.
Just replace constructor injection with property injection, and create no argument constructor:
#Component
public class BlogSummaryMailGenerator {
#Autowired
private BlogRepository blogRepository;
#Autowired
private BlogPostRepository blogPostRepository;
public BlogSummaryMailGenerator() {}
}
Actually, you do not need to declare an empty constructor. I did it just for clarity. Note, that BlogRepository and BlogPostRepository should be declared as beans (marked with #Component annotation, or created as #Bean in Spring configuration).
UPDATE:
When you add SpringComponentInjector in your WebApplication.init(), you can specify false for third paramter, which means 'wrapInProxies'. Wicket will never wrap Spring beans in porxy, and you can use #Autowired for constructors.
#Override
public void init()
{
super.init();
AnnotationConfigApplicationContext springContext =
new AnnotationConfigApplicationContext();
springContext.register(SpringConfig.class);
springContext.refresh();
getComponentInstantiationListeners().add(new SpringComponentInjector(this,
springContext, false));
}
The correct way to solve this is not to add Objenesis to your project, but to inject interfaces instead of concrete implementations, as #martin-g already explained (of course, we do not always have the privilege to be able to do the right thing, but when we do, we should do it).
I have a project that started to give the exact same error and stack after a library update I still don't exactly understand (complete Maven dependency hell, I inherited it, go easy on me). The reason was that I was creating a Spring request-scoped bean from a concrete subclass of ListModel<MyClass> and Wicket was hell bent on wrapping that class into a lazy loaded proxy, which it couldn't do because there was no zero-args-constructor.
I fixed it by changing the configuration class to create a named instance of IModel<List<MyClass>> and by defining the injected dependency using the name.
In the configuration class:
#Bean(name = "namedModel")
#RequestScope
public IModel<List<MyClass>> myObjectList() {
return new MyClass(parameters);
}
In the component:
#Inject
#Named("namedModel")
private IModel<List<MyClass>> myModel;
I have a utility class which I want to initialize when the application starts in Spring MVC. So I am implementing InitializingBean. Now I have to create an object for the same and save it in Application scope so that I can access the same instance everywhere. But I am not able to get hold of this.
Here is my try:
public class DashboardInitializer implements InitializingBean, ApplicationContextAware {
private ApplicationContext mApplication;
#Override
public void afterPropertiesSet() throws Exception {
initializeConfigurationUtil();
ConfigurationUtil util = ConfigurationUtil.getInstance();
/* Save the util to application scope */
}
#Override
public void setApplicationContext(ApplicationContext pApplication) throws BeansException {
this.mApplication = pApplication;
}
}
Is this approach correct or there is a better way to do that?
I think you need to simplify this a little bit.
You want the utility class to be initialized after your application context is loaded, but you also want your util class to be in the application context?
Seems the util class has some dependency objects configured in the application context, and the util class is in turn a dependency of some classes in the application context.
If you can express these dependencies in the form of beans (util is a bean, which has its dependency beans injected into it, and beans that need util have util injected into them), Spring will ensure that all dependencies of util are initialized first, then util is initialized and then it is injected into classes that need util.
You should not try to add something to an initialized context.. Its not possible.
If you cannot express util and its dependencies as beans, you can also take this approach:
1. Configure util as a bean in the application context, add a default constructor that does nothing. So this object would be created, but not initialized when the spring context is loaded.
In the ApplicationContextAware implementation you have, modify the setApplicationContext method. Get the util bean you configured earlier from the context.
You can now initialize (execute some code that you want to execute) the util instance, just make sure you do not try to reassign the bean to some other instance of util.
Hope this helps.
You can use #postconstruct annotation on methods to perform business logic immediately after the application has been initilized. And properties can simply be injected using placeholder in config and #Value annotation on java fields.
Is it possible to use #Configurable on a class that's weaved using AspectJ and get Spring to load in values on fields/methods which are annotated with #Value?
I know its possible with #Autowired and #Resource etc... Are there any others.
e.g.
#Configurable
public Class MyObj{
#Value("$(my.prop)")
private String aField;
public String getAField(){
return aField;
}
}
And then have something like
public aMethodSomewhereElse(){
MyObj obj = new MyObj()
assertNotNull(obj.getAField());
}
Are there any alternatives to being able to create MyObj with the new operator and still get spring to handle the annotations?
--EDIT:--
It IS possible to do this using new when using #Autowired, have a look at some Hibernate and JPA stuff with Spring and AOP... I've used this in the past to do some profiling of Java code. But I really want to use SPEL and #Value before I mock up a full example I was hoping to find the answer here. FYI - if you don't belive me the Spring Manual even says it is possible to do this, what I want to know is if its possible to use #Value annotations in the same scope...
The Spring container instantiates and configures beans defined in your
application context. It is also possible to ask a bean factory to
configure a pre-existing object given the name of a bean definition
containing the configuration to be applied. The spring-aspects.jar
contains an annotation-driven aspect that exploits this capability to
allow dependency injection of any object.
And...
Using the annotation on its own does nothing of course. It is the
AnnotationBeanConfigurerAspect in spring-aspects.jar that acts on the
presence of the annotation. In essence the aspect says "after
returning from the initialization of a new object of a type annotated
with #Configurable, configure the newly created object using Spring in
accordance with the properties of the annotation". In this context,
initialization refers to newly instantiated objects (e.g., objects
instantiated with the 'new' operator) as well as to Serializable
objects that are undergoing deserialization (e.g., via readResolve()).
http://static.springsource.org/spring/docs/3.0.0.RC2/reference/html/ch07s08.html
Cheers.
You are absolutely right - #Autowired fields will be wired in an #Configurable annotated class even outside of a Spring container, assuming that you have a AspectJ infrastructure in place.
You have noted a good catch though, #Value fields are processed by a Spring bean post processor(AutowiredAnnotationBeanPostProcessor), which resolves the #Value annotated fields. It does not act on objects instantiated outside of the container though - so in short, the #Autowired fields should get wired in, but #Value properties will not.
Doing
MyObj obj = new MyObj()
means that obj is not managed by spring, so it will not do autowiring.
Only way to do that is to obtain instance from an application context. For example:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyObj obj = context.getBean("myBean");
I don't think it is possible to use new operator and ask spring to autowire properties. I think 1 way to solve this is to get a static reference to applicationContext and create a prototype scoped bean.
#Component
public class ApplicationContextLocator {
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public ApplicationContextLocator() {
super();
}
#Autowired
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextLocator.applicationContext = applicationContext;
}
}
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Component
public class MyObj {
.....
}
public aMethodSomewhereElse(){
MyObj obj = ApplicationContextLocator.getApplicationContext().getBean(MyObj.class)
assertNotNull(obj.getAField());
}
I have an elaborate Spring bean setup for integration tests. Now I'm looking into writing a Robot library to expose my test data creation / behavior execution / assertion methods to Robot tests.
However what I understand from the Robot Framework user guide is that Robot can only instantiate library classes by calling a constructor. This is a bummer because I'd rather have my instances managed by Spring.
Ideally, I'd want to be able to give Robot the path to the application context and the bean name for the library. Failing that, I'd want Robot to be able to invoke a static factory method rather than a constructor, so I'm not forced to create a new instance.
One workaround I thought of is to create the Spring context in a static initializer and wire my dependencies by fetching beans from that context.
My original class looks like:
public class MyAwesomeTests {
#Autowired
private ThisHelper thisHelper;
#Autowired
private ThatHelper thatHelper;
// implementations of test steps and such
}
So I would change the above #Autowired fields to be protected, and create a subclass that statically initializes the Spring context and defines a Robot-friendly constructor:
public class RobotFriendlyTests extends MyAwesomeTests {
private static final ApplicationContext CONTEXT = new ClassPathXmlApplicationContext(...);
public RobotFriendlyTests() {
this.thisHelper = (ThisHelper) CONTEXT.getBean("thisHelper");
this.thatHelper = (ThatHelper) CONTEXT.getBean("thatHelper");
}
}
This should work, but it feels somewhat clunky. Is there a better way I should consider? Better yet, is there a Robot extension that already does this for me?
Have you thought about using Spring #Configurable, then even instances created by a normal new will become spring managed beans.
#See Spring Reference Chapter 7.8.1 Using AspectJ to dependency inject domain objects with Spring
There's a Robot Framework extension that supports using Spring to wire test libraries, take a look at: http://code.google.com/p/robotframework-javalibcore/wiki/SpringLibrary
I am not entirely sure whether it supports your case since I am not familiar at all with Spring.