I have a Spring Config which is working fine. My Spring Config uses multiple security:http sections.
When you define a security:http section, certain operations happen automagically, such as some bean definitions. One of these beans that get defined automatically, is a SessionAuthenticationStrategy -implementing bean.
Question: how can you identify which is which? For example I need to reference from code, via #Autowired, a specific authentication strategy, defined in a specific http:security tag; how can I accomplish this?
One way to have the same SessionAuthenticationStrategy instance in your custom bean and inside <sec:http>-spawned machinery is to go in the opposite direction: define SessionAuthenticationStrategy explicitly and inject it wherever you want, including http configuration:
<bean id="fancySessionAuthStrategy" class="com.fancy.FancySessionAuthStrategy">
...
</bean>
<sec:http ...>
<sec:session-management session-authentication-strategy-ref="fancySessionAuthStrategy"/>
...
</sec:http>
The only problem here is that you will have to manually build that strategy bean definition.
An example can be found in the documentation: http://docs.spring.io/spring-security/site/docs/current/reference/html/session-mgmt.html
Related
I'm trying to get a better understanding of the #Autowired annotations component scanning, but all the examples I found so far use context.getBean(..) at some point to get at least one Bean to start with.
I also read that doing that is considered bad practice , but I can't seem to find any information on how to do it without context.getBean(..)
Could somebody please enlighten me with an example and information on how to do this ?
Define your bean in xml and use
<context:component-scan base-package="com" />
<mvc:annotation-driven />
Bean def
<bean id="processEngine" class="com.processEngine">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
now you can get bean as following
#Autowired
private ProcessEngine processEngine;
how it works
spring scans the bean's recipes either from xml or java configuration. then spring creates a beanDefinitions which are 'loaded' into BeanFactory. BeanFactory triggers a set of BeanPostProcessors (BPP) which are scanning classes for particular annotations like Autowired/Resource/PostProcessor and etc. and do appropriate actions. in case when your class contains #Autowired annotation, AutowiredAnnotationBeanPostProcessor would auto wire required field (dependencies), and when creation of an object is done and all BPP worked out, object is ready to be used by the app, from this point your code can get 'ready' objects from container.
there are some cases when you would need to access this beans from the code which is out of spring's control and not managed by container. in order to do so, you would need to get the ApplicationContext (container) and call #getBean specifying either name or type. using applicationContext directly is not a good practice because there are some problems that you can come to, f.ex. id of a bean might be changed and if you refer to bean by id then NPE would be thrown.
configuration
there are several approaches to configure spring to scan the classes for finding bean recipes. one would be defining component-scan, in this case classes which are located in the path that you've set and having any of valid spring annotations like #Component, #Service, #Repository, #Controller (for web container) would be considered. another way would be specifying each bean separately using <bean> or #Bean.
examples.
if you want to create a web app then you should see DispatcherServlet with ContextLoaderListener classes. this classes would boot your app and load everything according to configuration. f.ex. here,
but if you want to create a desktop app, then you would end up with something like this
From time to time (usually when not using Spring Boot), I use something along the lines of the following code:
public static <T> T autowire(ApplicationContext ctx, T bean) {
ctx.getAutowireCapableBeanFactory().autowireBean(bean);
return bean;
}
In my main, I create an instance of the main application class that contains a few #Autowired annotations for the main services / entry points to my Spring application.
With Spring it is possible to inject a list of beans by the interface class like:
#Component
public class Service {
#Autowire
private List<InterfaceType> implementingBeans;
...
}
All defined beans that implement this interface will be present in this List.
The annotation based approach is not possible for me, as the Service class is in a module that must not have spring dependencies.
I need to use this mechanism from outside via xml configuration.
<bean id="service" class="...Service">
<property name="implementingBeans">
??? tell spring to create a list bean that resolves all beans of the interfaceType.
</property>
</bean>
Does anyone know how to solve this?
EDIT: Additionally, there are more than one spring applications that use this service. So the best solution would be to handle this szenario completely via xml configuration. I can then copy the xml parts to all spriong applications that need this.
I want to avoid having a kind of initializer bean that gets the service injected and must then be copied to all spring applications.
Kind regards.
An XML-only solution would simply have you declare a <bean> of the "external" type and provide an autowire value of "byType".
Controls whether bean properties are "autowired". This is an
automagical process in which bean references don't need to be coded
explicitly in the XML bean definition file, but rather the Spring
container works out dependencies.
[...]
"byType" Autowiring if there is exactly one bean of the property type in the container. If there is more than one, a fatal error is
raised, and you cannot use byType autowiring for that bean. If there
is none, nothing special happens.
The explanation is a little confusing in that we expect multiple InterfaceType beans, but the actual field is of type List and Spring will be able to dynamically instantiate one and add all the InterfaceType beans to it, then inject it.
Your XML would simply look like
<bean id="service" class="...Service" autowire="byType">
</bean>
My original suggested solution made use of SpEL.
In the module that does have Spring dependencies, create a DTO
#Component(value = "beanDTO")
public class BeanDTO {
#Autowire
private List<InterfaceType> implementingBeans;
public List<InterfaceType> getImplementingBeans() {
return implementingBeans;
}
}
and then use SpEL to retrieve the value of implementingBeans from the beanDTO bean.
<bean id="service" depends-on="beanDTO" class="...Service">
<property name="implementingBeans" value="{beanDTO.implementingBeans}" />
</bean>
Spring will create the BeanTDO bean, inject all the beans that are of type InterfaceType. It will then create the service bean and set its property from beanDTO's implementingBeans property.
Following comments on question:
In an effort to be more JSR 330 compliant, Spring has introduced support for Java EE's javax.inject package. You can now annotate your injection targets with #javax.inject.Inject instead of #Autowired. Similarly, you can use #Named instead of #Component. The documentation has more details.
let's say my app has a feature which can be enabled or disabled:
if disabled, spring beans (including endpoint mappings) will be loaded from main.xml
if enabled, spring beans (including endpoint mappings) will be loaded from main.xml and extra.xml.
The problem is my endpoint mapping has an id of "mynamespaceEndpointMapping". This bean is of the type org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping.
How do i define this bean in such a way that when it's loaded from main.xml it has only one endpoint but when it's loaded from extra.xml it has 10 endpoints? (I don't want all the 10 endpoints defined in main.xml if i have no use for them there) I could use bean inheritance but this would break the namespace naming convention since i would probably need different ids for the beans...
Thanks,
Teo
You need to override the spring bean. Like in this answer: Spring's overriding bean
But this is only possible with XML configuration and not with annotations.
EDIT: I meant the accepted answer. But I tested it with my own code.
I got 2 id's. In test1.xml
<bean id="test" class="Test1" />
and in test2.xml
<bean id="test" class="Test2" />
During startup is use both "test1.xml", "test2.xml" (in that order) in the ApplicationContext en when I get the Spring bean test it's of class Test2.
If I create a bean as follows:
#Repository("myRepository")
public class MyRepository {
...
}
In XML should I be able to wire it in as follows:
<bean id="xmlBean" class="uk.co.foo.myBean">
<constructor-arg ref="myRepository"/>
</bean>
Or is mixing like this not allowed?
The reason is for some things, generally business logic, it make sense for me to configure and wire various beans in XML as I may have multiple instances of the same interfaces, be likely to swap stuff round and it lets me to see my project configuration clearly from XML. However for repositorys it's very unlikely I am going to need to do or see any of those things and it's much more convenient just to use annotations.
It should work fine dont forget to enable context scanning in your xml configuration for Spring to find the bean it needs to AutoWire. You enable scanning by
<context:component-scan base-package="your package to scan" />
I want to inject a plain java object using Spring programmatically without using any xml configuration. Want to inject fields/methods annotated with tags Like #EJB, #PostConstruct etc. Is that possible? Thanks!
Creating an ApplicationContext without XML (using AnnotationConfigApplicationContext)
With AnnotationConfigApplicationContext, you don't need any XML at all. You create the Application context programatically and either
a) manually register annotated classes
appContext.register( MyTypeA.class,
MyTypeB.class,
MyTypeC.class );
b) or scan the classpath for annotated classes
appContext.scan(
"com.mycompany.myproject.mypackagea",
"com.mycompany.myproject.mypackageb"
)
If you use one of the convenience constructors
AnnotationConfigApplicationContext(Class<?> ... annotatedClasses)
or
AnnotationConfigApplicationContext(String ... basePackages)
the context is created and refreshed automatically, otherwise you need to call the refresh() method manually after adding the classes or packages.
Autowiring existing non-Spring beans (using AutowireCapableBeanFactory)
For autowiring an existing bean I think the preferred idiom is to use
appContext.getAutowireCapableBeanFactory().autowireBean(existingBean)
Or, if you want more control, use
appContext.getAutowireCapableBeanFactory()
.autowireBeanProperties(
existingBean,
autowireMode,
// e.g. AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE
dependencyCheck
)
For further reference, see
ApplicationContext.getAutowireCapeableBeanFactory()
AutowireCapeableBeanFactory.autowireBean(Object existingBean)
AutowireCapeableBeanFactory.autowireBeanProperties(Object
existingBean, int autowireMode,
boolean dependencyCheck)
Yes, you can annotate any POJO with #Component, #Service, #Controller, or #Respository (depending on its responsibilities), and it becomes a spring bean. You just have to put this line into the applicationContext.xml:
<context:component-scan base-package="org.yourbasepackage" />
You can also use #PostConstruct and #PreDestroy instead of the xml init-method and destroy-method.
Update: There is a project called spring-javaconfig. Parts of it have become part of the core spring and you can see more details here. In short, it allows you to use java classes instead of xml for configuring your beans.
The documentation around annotation-based Spring configuration can be found here. You will need a minimal amount of XML, so that Spring knows to look for annotation-based configuration:
<context:component-scan base-package=".." />
Once that is done, you can use the #Autowired annotation to set up your beans.