I have a Dynamic Web Project created in Eclipse (Juno) using Spring/Maven/Weblogic. I also have an Abstract class into which I inject a property (on the setter) via a properties file. The annotation used is #Value(value="${some.property}").
For some strange reason, when I deploy this project via maven to weblogic, the property gets injected for the concrete class that etends this Abstract class. But when I deploy this project directly onto weblogic via the Server -> Add Deployment, it fails to inject the property. In fact it does inject properties for all other annotations on the concrete class but ignores any annotations for the abstract class.
So basically this has nothing to do with coding but seems like some kind of config problem. Has anyone encountered something similar. Thanks.
public abstract class MyAbstract {
#Value(value="${myproperty1}")
public void setMyValue(String myValue) {
log.debug("setMyValue({})", myValue);
this.myValue = myValue;
}
}
public class MyConcrete {
#Value(value="${myproperty2}")
public void setMyValue2(String myValue2) {
log.debug("setMyValue2({})", myValue2);
this.myValue2 = myValue2;
}
}
I found the issue. The thing is that this particular bean has #Scheduled annotation and hence does not qualify for Bean Post Processing. Since the properties via #Value are set during this phase, they are skipped. Instead I shifted the bean creation into my application context xml file and set the properties from there eg.
<bean id="myConcrete" class="some.package.MyConcrete"
p:value="${myproperty1}"
/>
Now the properties are getting injected during normal bean lifecycle i.e. after Instantiation but before Bean Post Processor.
Related
I'm looking for a pattern to simplify bean creation for a team of developers.
For now, I've been trying to use abstract classes like this:
public abstract class BaseClass {
#Bean
public BeanA generateBeanA() {
...
return beanA;
}
#Bean
public BeanB generateBeanB() {
...
return beanB;
}
}
The idea behind: I provide the BaseClass and I'd like developers to extend it many times. For each extension, every beans should be generated. But this approach doesn't work : for each extension, developers have to redeclare beans for 2 reasons :
bean declaration is not inherited
to avoid name clashing, they have to name beans manually in each extension
Is there a better pattern that would allow the following?
centralized bean naming (ie: the developer declare a base name in the extension and every bean of the extension is renamed accordingly: ${baseName}${beanName} )
overriden beans would be declared (instead of parent version)
parent beans would be declared if not overriden
There are 3 ways to configure beans in Spring container:
Declare them using XML configuration.
Declare beans using the #Bean
annotation in a configuration class.
Mark the class with one of the
annotations from the org.springframework.stereotype package, and
leave the rest to component scanning.
So, the way you declare Spring bean is wrong.
IMHO, let the developers declare beans as they want, and they just #Autowired them or something.
Please continue by reading this
Team, I am working on an Spring boot application which uses lot of other third party libraries.
All those libraries are built on top of spring core.
The common issue that usually comes is DuplicateBeanException.
Let's say if the bean-name is same from different libraries, spring throws error while trying to start the server. As I do not have control over third party jars. I have to rename the beans in my application: below is the code snippet I wrote to handle this scenario. But this is not an efficient solution as in future there can be again some duplicate beans. How can I solve it in a generic way so that when ever any duplicate beans come, my application can handle and initialize those beans.
My code to handle duplicate bean :
#Configuration
public class ExternalBeanConfiguration {
#Bean(employeeLib1)
public Employee getEmployee() {
return new Employee();
}
#Bean(employeeLib2)
public com.another.library.Employee getEmployee() {
return new com.another.library.Employee();
}
}
When you configure where to scan the beans from the external libraries by #ComponentScan , you can specify a BeanNameGenerator for how the name of the detected beans are defined.
#Configuration
#ComponentScan(basePackages = { "com.foo.lib1" , "com.foo.lib2"}, nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class)
public class ExternalBeanConfiguration {
}
The FullyQualifiedAnnotationBeanNameGenerator is exactly for solving your problem which is mentioned in the javadoc as :
Favor this bean naming strategy over {#code
AnnotationBeanNameGenerator} if you run into naming conflicts due to
multiple autodetected components having the same non-qualified class
name (i.e., classes with identical names but residing in different
packages)
It will name the bean as the fully qualified class name as the default bean name such that even if different packages has a same class name , it will still have different bean name.
I have such app conf in, jar which will be added to the classpath after startup:
#Configuration
#ComponentScan("com.transportexchangegroup.testConf")
public class AppConf {
}
How to load beans dynamically? I saw solutionsm when it is required to write and add bean definitions, but if we do not know everything about new beans and just want to load them automatically?
Class conf = jarService.loadClass("com.x.testConf.AppConf");
((AnnotationConfigServletWebServerApplicationContext) applicationContext).register(conf);
((AnnotationConfigServletWebServerApplicationContext) applicationContext).refresh();
As I see, refresh() turns off web app started locally from IDE.
Do you know any other solutions or what is wrong? Will this work for spring rest controllers from jar?
I'm not sure what do you mean "dynamically".
In general you can load beans if some condition applies, usually depending on the configuration. So you can do something like this:
application.properties: // or yaml it doesn't matter
feature.enabled=true
#Component
#ConditionalOnProperty(name="feature.enabled", havingValue="true", matchIfMissing="true" / "false") // matchIfMissing depends on whether you want the bean to be loaded if the property is not defined
public MyBean {
}
Some caveats:
If you have many beans that depend on "business" feature in order to avoid placing #ConditionalOnProperty you can do one of the following:
Define your own #Component annotation:
// runtime retention, place on class
#Component
#ConditionalOnProperty(...)
#MyFeatureComponent
... and use it in all the beans that define the feature:
#MyFeatureComponent
public class MyBean
{}
Use Java Configuration instead of annotations:
#Configuration
#ConditionalOnProperty(...)
public class MyFeatureConfiguration {
#Bean
public MyBean myBean(){return new MyBean();}
#Bean
public MyAnotherBean myAnotherBean(){return new MyAnotherBean();}
}
In this case you don't need to place any annotation on MyBean at all.
Spring also has a concept of profiles which is just the same, something that it under the hood implemented with these conditionals.
It allows however to define configuration files per profile, so you might want to read about #Profile annotation as well.
As for the bean definitions - this is way more advanced stuff, in general when spring loads it "recognizes" which bean should be loaded and in which order and for doing that it creates a bean definition before loading the bean. So if you hook into this process you can define your own bean definitions if you want and spring will create beans based on these definitions as well. So basically its a hook that allows altering the bean defitions / create new one during the startup process and hence affect the actual beans that will be loaded into the application context.
I doubt, but if you really need that, read about Bean Factory Post Processors in spring.
I have below working groovy code from Spring framework project:
import org.springframework.oxm.Unmarshaller
public class ItemSearchService {
Unmarshaller unmarshaller;
public ItemSearchResponse getObject(InputStream xml) {
ItemSearchResponse its = null;
try {
its = (ItemSearchResponse) unmarshaller.unmarshal(new StreamSource(xml));
} finally {
}
return its;
}
}
Unmarshaller.unmarshall is actually interface method:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/oxm/Unmarshaller.html
Unmarshaller interface is implemented by several classes.
Who decides which implementing class to inject during runtime and how it decides which class to use?
Does Spring IoC mechanism does this? If so does it pick up one specific implementing class during build time when jar is generated or it does it during run time?
Also how to know which implementing class it actually used?
Will above code work outside of Spring in ordinary Java file assuming dependent jars in classpath?
As soon as it goes about a Grails project (not a pure Spring one), some things should be clarified.
Who decides which implementing class to inject during runtime and how it decides which class to use? Does Spring IoC mechanism does this? If so does it pick up one specific implementing class during build time when jar is generated or it does it during run time?
What Spring does in a plain Spring(Boot) is nicely described by #svr s answer and other documentation on the Internet, but has not much to do with your case.
In Grails the convention-over-configuration doctrine is used, meaning that
by default Bean Autowiring is active
only beans which are declared as Grails artefacts, like Service are auto-injected.
Usually, if you want to autowire a bean of other stereotype, you have to declare it somewhere, otherwise Spring IoC container inside Grails simply won't find it.
You shall check your grails-app/conf/spring folder for resources.groovy (or maybe yaml or xml files depending on version ) and see if your unmarshaller bean is defined there. It should look like:
beans = {
unmarshaller Unmarshaller ....
}
So, basically it doesn't matter how many implementations of Unmarshaller interface are present in all project's jar files. The only thing what matters is what defined in your resources.groovy.
If you want to check the class of the bean in runtime, just log it's class in your service:
class ItemSearchService {
Unmarshaller unmarshaller
ItemSearchResponse getObject(InputStream xml) {
log.info "unmarshaller's class is $unmarshaller.class"
// or
// println "unmarshaller's class is $unmarshaller.class"
}
}
Who decides which implementing class to inject during runtime and how
it decides which class to use?
Does Spring IoC mechanism does this? If so does it pick up one
specific implementing class during build time when jar is generated or
it does it during run time?
Yes Spring IOC container. It happens at run time when the application is run.
Also how to know which implementing class it actually used?
For most part you will have to define bean with implementation to pick. For other cases you can look at the spring auto configuration classes.
Will above code work outside of Spring in ordinary Java file assuming
dependent jars in classpath?
Not sure what you mean outside of Spring but as long as application is packaged correctly it should all work.
Quick Overview
Spring IOC will only inject a bean when found in the application context. An application context loosely is repository of beans.
Classpath Scanning and Registration
Spring scans application to pick up all the stereotyped classes and registers bean definition with application context. Stereotyped annotations include #Component, #Repository, #Service, #Controller, #Configuration. More
Dependency Injection
Spring DI creates the bean and injects them as dependencies into application. You can create dependencies between different application components using the registered beans and spring will autowire these for you. More. There are two types of DI - Constructor based and setter based - Constructor for required dependencies and setter based for optional dependencies. More
There are sensible defaults provided when you use any spring classes. You just have to define the bean where there is no default or you would like to pick different implementation. Application context can be further be enriched by using Spring Boot Auto Configuration where all related classes are wired together to form a coherent entry classes. You can then easily inject these into application for getting started. More
Example
You can define bean in the #Configuration class for a web service module.
#Configuration
public class WSConfig {
#Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marsharller = new Jaxb2Marshaller();
marsharller.setContextPath("some package");
}
#Bean
public WebServiceTemplate webServiceTemplate(Jaxb2Marshaller marsharller) {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate(marsharller);
}
}
#RequiredArgsConstructur
public class ItemSearchService {
private final Unmarshaller unmarshaller;
public ItemSearchResponse getObject(InputStream xml) {
ItemSearchResponse its = null;
try {
its = (ItemSearchResponse) unmarshaller.unmarshal(new StreamSource(xml));
} finally {}
return its;
}
}
This similar configuration is automatically taken care by WebServicesAutoConfiguration with ways to customize when using Spring Boot.
I have an application which has a very simple plugin architecture by the means of registering additional behaviour using spring classpath scanning ("Installing" the plugin happens by putting the plugin.jar on the classpath).
This works great for registering additional beans and it also works great for registering hooks like this:
// core.jar:
#Component
class CoreClass {
public void addListener(Listener listener) { /* ... */ }
}
// plugin.jar
#Component
class Plugin {
public Plugin(CoreClass coreClass) {
coreClass.addListener(new PluginListener());
}
}
However sometimes it is more appropriate to to replace an entire bean. This might look like this:
// core.jar:
#Component("someBean")
class CoreClass implements CoreInterface {
#Override
public void doStuff();
}
// plugin.jar
#Component("someBean")
#Order(HIGHEST_PRECEDENCE)
class Plugin implements CoreInterface {
#Override
public void doStuff();
}
In this case I want that both Plugin and CoreClass are discovered by classpath scan during startup, but then the CoreClass should be ignored, because the bean someBean has another definition with higher precedence.
I am aware that I could do this using XML (<import resource="classpath*:plugin-spring.xml" />), because XML allows overriding definitions. But is this also possible using annotations?
Edit: Note that I sometimes have multiple bean instances of the same type (with different properties) which I inject name-based. Thus I actually need to override the bean with a certain name.
Possible solution to use:
#Primary
Indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency. If exactly one 'primary' bean exists among the candidates, it will be the autowired value.
This annotation is semantically equivalent to the element's primary attribute in Spring XML.
May be used on any class directly or indirectly annotated with #Component or on methods annotated with #Bean.
// core.jar:
#Component
class CoreClass implements CoreInterface {
#Override
public void doStuff();
}
// plugin.jar
#Component
#Primary
class Plugin implements CoreInterface {
#Override
public void doStuff();
}
http://memorynotfound.com/handling-multiple-autowire-candidates-with-spring-primary/
Or you could use :
#Configuration
#ImportResource( { "classpath*:core-spring.xml", "classpath*:plugin-spring.xml" } )
public class ConfigClass { }
I suspect that problem with annotations is not clear which order to override, if you define over notations same name you will end-up with ConflictingBeanDefinitionException spring will not allow you to have #Component or #Bean with same name. In xml you can manage override order that’s why you can do this over xml. In annotations you can't do that.
Any given Spring context can only have one bean for any given id or name. In the case of the XML id attribute, this is enforced by the schema validation. In the case of the name attribute, this is enforced by Spring's logic.
However, if a context is constructed from two different XML descriptor files, and an id is used by both files, then one will "override" the other. The exact behavior depends on the ordering of the files when they get loaded by the context.
So while it's possible, it's not recommended. It's error-prone and fragile, and you'll get no help from Spring if you change the ID of one but not the other.
However, if a context is constructed from two different XML descriptor files, and an id is used by both files, then one will "override" the other. The exact behavior depends on the ordering of the files when they get loaded by the context.