Bean into bean injection [closed] - spring

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
Have no experience with Spring beans injection.
<beans:bean id="ModeService"
class="<path>Service">
<beans:property name="Mode" value="true"/>
</beans:bean>
<beans:bean id="Filter"
class="<path>.RequestFilter">
<custom-filter position="FIRST" />
</beans:bean>
How to inject ModeService bean into Filter bean ?
ok, I've got injection in Spring thx #William
So have:
<beans:bean id="maintenanceModeService"
class="<path>.MaintenanceService">
<beans:property name="maintenanceMode" value="true"/>
</beans:bean>
<beans:bean id="maintenanceFilter"
class="<path>.MaintenanceRequestFilter">
<custom-filter position="FIRST" />
<beans:property name="modeService" ref="maintenanceModeService"/>
</beans:bean>
In MaintenanceService, I've append setter/getter for invoking variable:
boolean maintenanceMode;
public void setMaintenanceMode(boolean mode)
{
this.maintenanceMode = mode;
}
public boolean getMaintenanceMode()
{
return maintenanceMode;
}
And append setter/getter into MaintenanceRequestFilter:
boolean modeService;
public void setModeService(MaintenanceService maintenanceMode)
{
this.modeService = maintenanceMode;
}
public MaintenanceService getMaintenanceMode()
{
return modeService;
}
And then invoke modeService in doFilter()
But smth wrong...

<beans:bean id="Filter" class="<path>.RequestFilter">
<custom-filter position="FIRST" />
<beans:property name="modeService" ref="ModService"/>
</beans:bean>
And you should have a getter/setter method in your class
class RequestFilter{
public void setModeService(ModService modService){
// some set code here
}
public ModeService getModeService(){
// some set code here
return modService;
}
}

You can use ref attribute to define reference to another bean. Filter class should have property of type ModeService so that you can define it in <property> tag using ref attribute.
<beans:bean id="Filter" class="<path>.RequestFilter">
<custom-filter position="FIRST" />
<beans:property name="modeService" ref="ModeService"/>
</beans:bean>

Related

Spring resolve view name dynamically at runtime based on language

I have a web application where page is displayed in English language. There is a button on header section, clicking on it will change the page to Dutch language. (I will store it in cookie). For this I have to load different JSP, CSS, IMAGE folder. Like, I have below files in folder:
helloPortal.jsp
helloPortal_DU.jsp
I don't want to change each and every Controller class to check for language and set ModelView name accordingly. Instead I will say ModelAndView("helloPortal") and want Spring to do it from InternalResourceViewResolver or some other mechanism.
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean> here
I need another ViewResolver where based on language it Suffix _DU.jsp to file name
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value="_DU.jsp" />
</beans:bean>
I googled for this kind of solution but can't find precise solution. InternalResourceViewResolver is for properties file I believe. Is there a way based on cookie/locale change viewName dynamically.
Please let me know if I haven't explained my issue properly.
You could create custom view resolver. The resolver could check the cookies to figure out it needs to resolve to a Dutch version of the view, modify the view name appropriately and then delegate to normal view resolver that you are currently using.
Implementation could look something like this (I haven't tested it, but it should work):
public class DelegatingLocalizedViewResolver implements ViewResolver {
#Autowired
private HttpServletRequest httpServletRequest;
private ViewResolver delegateViewResolver;
#Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
if (isDutchLanguage()) {
return delegateViewResolver.resolveViewName(viewName + "_DU", locale);
}
return delegateViewResolver.resolveViewName(viewName, locale);
}
private boolean isDutchLanguage() {
Cookie[] cookies = httpServletRequest.getCookies();
// ... do cookie logic to figure out if the request is dutch
return true;
}
public void setDelegateViewResolver(ViewResolver delegateViewResolver) {
this.delegateViewResolver = delegateViewResolver;
}
}
XML config would then look something like this:
<beans:bean id="internalResourceViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<beans:bean class="org.example.DelegatingLocalizedViewResolver">
<beans:property name="delegateViewResolver" ref="internalResourceViewResolver" />
</beans:bean>
PS. You might look into Spring's internationalization / localization support and leverage it instead of storing language in the cookie yourself (especially if you plan to support more languages in the future). Once Spring's localization support is enabled, you will get the country/language information in Locale object in the ViewResolver.

How to Over ride BindAuthenticator handleBindException for Spring LDAP Authentication setup in Spring Boot

For Spring security setup in Spring Boot. The LDAP Authentication provider is configured by default to use BindAuthenticator class.
This Class contains method
/**
* Allows subclasses to inspect the exception thrown by an attempt to bind with a
* particular DN. The default implementation just reports the failure to the debug
* logger.
*/
protected void handleBindException(String userDn, String username, Throwable cause) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to bind as " + userDn + ": " + cause);
}
}
This Method is to handle the authentication related Exceptions like invalid credentials.
I want to over-ride this method so i can handle this issue and return proper error message on the basis of error codes returned by LDAP. like invalid password or the account is locked.
Current LDAP implementation always returns "Bad Credentials" that does not give the right picture that why my credentials are invalid. i want to cover the cases
where the account is Locked
password is expired so i can redirect to change password
account locked due to number of invalid password retries
Please help
The issue i fixed by defining the LDAP context instead of using the Spring Boot LDAPAuthenticationProviderConfigurer.
Then created the FilterBasedLdapUserSearch and Over-written the BindAuthentication with my ConnectBindAuthenticator.
i created a separate LDAPConfiguration class for spring boot configuration and registered all these custom objects as Beans.
From the above Objects i created LDAPAuthenticationProvider by passing my Custom Objects to constructor
The Config is as below
#Bean
public DefaultSpringSecurityContextSource contextSource() {
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(env.getProperty("ldap.url"));
contextSource.setBase(env.getProperty("ldap.base"));
contextSource.setUserDn(env.getProperty("ldap.managerDn"));
contextSource.setPassword(env.getProperty("ldap.managerPassword"));
return contextSource;
}
#Bean
public ConnectBindAuthenticator bindAuthenticator() {
ConnectBindAuthenticator connectBindAuthenticator = new ConnectBindAuthenticator(contextSource());
connectBindAuthenticator.setUserSearch(ldapUserSearch());
connectBindAuthenticator.setUserDnPatterns(new String[]{env.getProperty("ldap.managerDn")});
return connectBindAuthenticator;
}
#Bean
public LdapUserSearch ldapUserSearch() {
return new FilterBasedLdapUserSearch("", env.getProperty("ldap.userSearchFilter"), contextSource());
}
You have to change your spring security configuration to add your extension of BindAuthenticator:
CustomBindAuthenticator.java
public class CustomBindAuthenticator extends BindAuthenticator {
public CustomBindAuthenticator(BaseLdapPathContextSource contextSource) {
super(contextSource);
}
#Override
protected void handleBindException(String userDn, String username, Throwable cause) {
// TODO: Include here the logic of your custom BindAuthenticator
if (somethingHappens()) {
throw new MyCustomException("Custom error message");
}
super.handleBindException(userDn, username, cause);
}
}
spring-security.xml
<beans:bean id="contextSource"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<beans:constructor-arg value="LDAP_URL" />
<beans:property name="userDn" value="USER_DN" />
<beans:property name="password" value="PASSWORD" />
</beans:bean>
<beans:bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<beans:constructor-arg index="0" value="USER_SEARCH_BASE" />
<beans:constructor-arg index="1" value="USER_SEARCH_FILTER" />
<beans:constructor-arg index="2" ref="contextSource" />
</beans:bean>
<beans:bean id="ldapAuthProvider"
class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<beans:constructor-arg>
<beans:bean class="com.your.project.CustomBindAuthenticator">
<beans:constructor-arg ref="contextSource" />
<beans:property name="userSearch" ref="userSearch" />
</beans:bean>
</beans:constructor-arg>
</beans:bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="ldapAuthProvider" />
</security:authentication-manager>
Hope it's helpful.

How to implement own OpenIDConsumer on Spring Security?

I want to implement a new OpenIDConsumer for Spring Security OpenID. I implemented OpenIDConsumer in a class and then added the corresponding configuration to applicationContext-security.xml, but my code doesn't seems to be executed at all.
This is the relevant part from applicationContext-security.xml:
<http auto-config="false">
<intercept-url pattern="/**" access="ROLE_USER"/>
<openid-login login-page="/auth/login"
authentication-failure-url="/auth/login?login_error=true">
<attribute-exchange>
<openid-attribute name="email" type="http://axschema.org/contact/email" required="true"/>
</attribute-exchange>
</openid-login>
</http>
<b:bean id="openIdConsumer" class="sample.OpenIDTestConsumer">
<b:property name="email" value="email"/>
</b:bean>
Now, the class sample.OpenIDTestConsumer is initialized but it is not used by Spring Security, and the original class is used instead I think OpenID4JavaConsumer.
The sample.OpenIDTestConsumer class implements the OpenIDConsumer interface and it is initialized and the setEmail method is set, but it doesn't execute the beginConsumption or endConsumption methods, that's why I think it is just created because of applicationContext-security.xml bean definition but is not used.
The question is: How can I glue or set a custom class to work as the OpenIDConsumer and not use the Spring implementation?
By default Spring Security registers an OpenIDAuthenticationFilter with an OpenID4JavaConsumer when using the security namespace configuration. You can not define a custom consumer with the namespace. A solution would be to use a custom filter and configure the OpenIDAuthenticationFilter by hand in your applicationContext-security.xml:
<http ...>
...
<custom-filter position="OPENID_FILTER" ref="openIdFilter" />
</http>
<b:bean id="openIdFilter" class="org.springframework.security.openid.OpenIDAuthenticationFilter">
<b:property name="consumer" ref="openidConsumer" />
<!-- customize your filter (authentication failure url, login-page, … -->
</b:bean>
<b:bean id="openIdConsumer" class="sample.OpenIDTestConsumer">
<!-- config attribute exchange here -->
<b:property name="email" value="email"/>
</b:bean>
Another solution is to use a tip from the FAQ and use a BeanPostProcessor. The result might look something like this:
public class CustomOpenidConsumerBeanPostProcessor implements BeanPostProcessor {
private OpenIDConsumer openidConsumer;
public Object postProcessAfterInitialization(Object bean, String name) {
if (bean instanceof OpenIDCOnsumer) {
return openidConsumer;
}
return bean;
}
public Object postProcessBeforeInitialization(Object bean, String name) {
return bean;
}
public void setOpenidConsumer(OpenIDConsumer openidConsumer) {
this.openidConsumer = openidConsumer;
}
}
Then your configuration would include the following:
<b:bean class="CustomOpenidConsumerBeanPostProcessor">
<b:property name="openidConsumer" ref="openIdConsumer"/>
</b:bean>
<b:bean id="openIdConsumer" class="sample.OpenIDTestConsumer">
<!-- config attribute exchange here -->
<b:property name="email" value="email"/>
</b:bean>

JSF ManagedBean - injected properties not working correctly on STATE_SAVING_METHOD=client

I am into a problem from two days and I can not get out from this.
The problem I am having is using a MangedBean property after the deserialization (I guess).
The property (purchaseManager) is set up with Spring, and use a DAO which extends MyBatis as data mapper to interact with the DB.
In fact, on the first access to the page, purchaseManager.getAll() inside init() method works fine.
When i try to call refreshList() as an action from a button, I have a NullPointerException on the getSqlSession() inside the DAO.
Letting only the relevant code the situation is as follow:
#ManagedBean(name = "purchaseController")
#ViewScoped
public class PurchaseController implements Serializable{
#ManagedProperty(value = "#{purchaseManager}")
private PurchaseManager purchaseManager;
#PostConstruct
public void init(){
purchaseManager.getAll();
}
public void refreshList(){
purchaseManager.getAll();
}
}
public class PurchaseManagerImpl implements PurchaseManager, Serializable {
PurchaseDAO purchaseDAO;
public void getAll() {
purchaseDAO.getAll()
}
}
public class PurchaseDAOImpl extends SqlSessionDaoSupport implements PurchaseDAO, Serializable {
public void getAll() {
SqlSession session = getSqlSession(); // when the call comes from refreshList(), session is null
session.selectList("PAYMENT.getAll", null);
}
}
in web.xml
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
If I change the STATE_SAVING_METHOD to server the application works fine but is not what I want. Same thing if I make the ManageBean as RequestScope but this too will penalize my requirements.
Thank you in advance to anyone for any kind of help!
Ermal
Solved the error adding <aop:scoped-proxy proxy-target-class="false" /> to the definition of the service/manager declared through Spring. This makes possible the injection of a fully serializable proxy instance.
<bean id="purchaseManager" class="al.ozone.bl.manager.impl.PurchaseManagerImpl">
<property name="purchaseDAO" ref="purchaseDAO" />
<aop:scoped-proxy proxy-target-class="false" />
</bean>
proxy-target-class="false" is for telling that PurchaseManagerImpl implements already an interface. If setted to true or omitted, CGLIB2 library must be used.
In this way JSF is correctly taking data from DB using Spring+MyBatis.
The mistery (for me) on this point (more theorical) is :
Is MyBatis object (PurchaseDAOImpl) and the dataSource, correctly handled behind the scenes?
Are they recreated or restored on each HTTP request?
Remember that I have STATE_SAVING_METHOD=client and BackingBean as ViewScope. My Goal is to have the server lighter possible because I expect an hight number of user interactions.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="poolPreparedStatements" value="true" />
<property name="defaultAutoCommit" value="false" />
</bean>
Thank you very much to anyone for some light on this matter!
Consulted links:
Spring session-scoped beans (controllers) and references to services, in terms of serialization
http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-scopes-other-injection
http://www.infoq.com/presentations/Whats-New-in-Spring-3.0

spring 3 my converter is not used

...but registered
Using Spring 3
I have two converters registered as follows:
<beans:bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<beans:property name="converters">
<beans:list>
<beans:bean class="mypackage.CalendarToStringConverter" />
<beans:bean class="mypackage.StringToCalendarConverter" />
</beans:list>
</beans:property>
</beans:bean>
The converters look like this:
public class StringToCalendarConverter implements Converter< String, Calendar > {
public Calendar convert( String value ) {
return Calendar.getInstance();
}
}
public class CalendarToStringConverter implements Converter< Calendar, String > {
public String convert( Calendar arg0 ) {
return "23.10.1985";
}
}
The problem is that they are not used during conversion in post and get requests.
What am I doing wrong?
What do I havt to do to get this working?
THX!
Are you using <mvc:annotation-driven> and if so, are you pointing to conversionService in the conversion-service attribute?
Here's the converters configuration that works for me. The differences you might try changing:
I pass in a set instead of a list. (setConverters takes a Set parameter)
I use FormattingConversionServiceFactoryBean instead of ConversionServiceFactoryBean. (Should not matter)
My converters are defined as top level beans and referenced. (Also should not matter)
Hopefully one of this will fix your problem.
<util:set id="converters" >
<ref bean="userDao" />
<ref bean="orderDao" />
<util:set>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters" ref="converters"/>
</bean>

Resources