Spring MVC Mixing xml and java @ContextConfiguration in integration test -
i trying configure spring mvc integration test using combination of xml config , @configuration
annotated classes.
@runwith(springjunit4classrunner.class) @webappconfiguration @testpropertysource({"/spring-security.properties", "/rabbitmq-default.properties", "/mongodb-default.properties", "/webapp-override.properties"}) @contexthierarchy({ @contextconfiguration("classpath:**/security-config.xml"), @contextconfiguration(classes = rootconfig.class), @contextconfiguration(classes = springmvcconfig.class) }) public class baseconfiguredmvcintegrationtest { }
the java configurations initialized correctly. problem although "**/security-config.xml"
file found , parsed during initialization... spring security beans defined in there never registered in webapplicationcontext
.
caused by: org.springframework.beans.factory.nosuchbeandefinitionexception: no qualifying bean of type [org.springframework.security.crypto.bcrypt.bcryptpasswordencoder] found dependency: expected @ least 1 bean qualifies autowire candidate dependency. dependency annotations: {@org.springframework.beans.factory.annotation.autowired(required=true)} @ org.springframework.beans.factory.support.defaultlistablebeanfactory.raisenosuchbeandefinitionexception(defaultlistablebeanfactory.java:1301) @ org.springframework.beans.factory.support.defaultlistablebeanfactory.doresolvedependency(defaultlistablebeanfactory.java:1047) @ org.springframework.beans.factory.support.defaultlistablebeanfactory.resolvedependency(defaultlistablebeanfactory.java:942) @ org.springframework.beans.factory.annotation.autowiredannotationbeanpostprocessor$autowiredfieldelement.inject(autowiredannotationbeanpostprocessor.java:533)
so question how utilize both xml based , annotated based configuration in spring mvc integration test?
i change spring security config java/annotated based one... rather not this. find using spring security namespace more readable , concise using java config.
also, note combined xml/java configuration works fine in non-test environment.
- spring v4.1.6
- spring security v4.0.1
webapplicationcontext config:
package com.gggdw.web.config; import javax.servlet.filterregistration; import javax.servlet.servletcontext; import javax.servlet.servletexception; import javax.servlet.servletregistration; import org.springframework.context.annotation.configuration; import org.springframework.web.webapplicationinitializer; import org.springframework.web.context.contextloaderlistener; import org.springframework.web.context.support.annotationconfigwebapplicationcontext; import org.springframework.web.filter.delegatingfilterproxy; import org.springframework.web.filter.hiddenhttpmethodfilter; import org.springframework.web.servlet.dispatcherservlet; @configuration public class gggwebinitializer implements webapplicationinitializer { public static final string servlet_name = "ggg"; @override public void onstartup(servletcontext servletcontext) throws servletexception { // create 'root' spring application context annotationconfigwebapplicationcontext rootcontext = new annotationconfigwebapplicationcontext(); rootcontext.register(rootconfig.class); // manage lifecycle of root application context servletcontext.addlistener(new contextloaderlistener(rootcontext)); // create dispatcher servlet's spring application context annotationconfigwebapplicationcontext dispatchercontext = new annotationconfigwebapplicationcontext(); dispatchercontext.register(springmvcconfig.class); // register , map dispatcher servlet servletregistration.dynamic dispatcher = servletcontext.addservlet(servlet_name, new dispatcherservlet(dispatchercontext)); dispatcher.setloadonstartup(1); dispatcher.addmapping("/"); //spring security config filterregistration.dynamic springsecurityfilterchain = servletcontext.addfilter( "securityfilter", new delegatingfilterproxy("springsecurityfilterchain")); springsecurityfilterchain.addmappingforservletnames(null, false, servlet_name); //springsecurityfilterchain.setasyncsupported(true); servletcontext.addfilter("hiddenhttpmethodfilter", hiddenhttpmethodfilter.class); } }
rootconfig.class
@configuration @import({webpropertiesconfig.class, // loads properties files on class path resources folder mongoconfig.class // init mongodb connection }) @importresource({"classpath:**/security-config.xml"}) // spring security xml config (java config not readable) public class rootconfig { }
security-config.xml
<?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:security="http://www.springframework.org/schema/security" xmlns:context="http://www.springframework.org/schema/context" xsi:schemalocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- <context:property-placeholder location="classpath:spring-security.properties" /> --> <security:global-method-security pre-post-annotations="enabled" secured-annotations="enabled"> <security:expression-handler ref="expressionhandler"/> </security:global-method-security> <bean id="expressionhandler" class="org.springframework.security.access.expression.method.defaultmethodsecurityexpressionhandler"> <property name="permissionevaluator" ref="permissionevaluator"/> </bean> <bean id="permissionevaluator" class="com.my.local.package.security.genericpermissionevaluator"> </bean> <!-- configure spring security --> <security:http auto-config="true" use-expressions="true" > <security:form-login login-page="${spring.security.login-page}" login-processing-url="${spring.security.login-processing-url}" default-target-url="${spring.security.default-target-url}" authentication-failure-url="${spring.security.authentication-failure-url}" username-parameter="${spring.security.username-parameter}" password-parameter="${spring.security.password-parameter}" /> <security:logout logout-url="${spring.security.logout-url}" logout-success-url="${spring.security.logout-success-url}" /> <security:intercept-url pattern="/**" requires-channel="https" /> <security:intercept-url pattern="/s/**" access="isauthenticated()" requires-channel="https" /> <security:custom-filter ref="log4jmdcfilter" after="security_context_filter"/> <security:access-denied-handler error-page="${spring.security.access-denied-handler-error-page}" /> <!-- <security:session-management invalid-session-url="${spring.security.invalid-session-url}"/> 2 types of invalid session, brand new user , timeout of previous logged in user both need handled differently --> </security:http> <bean id="customuserdetailsservice" class="com.my.local.package.customuserdetailsservice" depends-on="userrepository"/> <bean id="bcryptpasswordencoder" class="org.springframework.security.crypto.bcrypt.bcryptpasswordencoder" /> <!-- log4j filter add username , ipaddress logging on per request/thread basis --> <bean id="log4jmdcfilter" class="com.my.local.package.filter.log4jmdcfilter"/> <security:authentication-manager> <security:authentication-provider user-service-ref="customuserdetailsservice"> <security:password-encoder ref="bcryptpasswordencoder"/> </security:authentication-provider> </security:authentication-manager> </beans>
update: upon further consideration , based on latest feedback, behavior you're experiencing might result of bug introduced in spring framework 4.1.4 (see spr-13075 details).
try downgrading spring framework 4.1.3, , let me know if still experience undesired behavior.
note combined xml/java configuration works fine in non-test environment.
how so?
do literally have 3 (3) contexts loaded in hierarchy in production?
i doubt that. rather, assume somehow loading single root webapplicationcontext
"classpath:**/security-config.xml"
, rootconfig.class
.
thus, important question is: how configuring root webapplicationcontext in production?
once have answered that, can tell how achieve same thing in test configuration. ;)
regards,
sam (author of spring testcontext framework)
Comments
Post a Comment