Spring webflow can't access mvc beans - java

I'm trying to use some #Service annotated classes (yes, using the mvc:annotation-driven) within the following Web flow :
manage-flow.xml
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd" start-state="start" >
<view-state id="start" view="Userview.jsp" >
<on-render>
<set name="flowScope.users"
value="UserService.getUsers()">
</set>
</on-render>
</view-state>
<bean-import resource="Manage-Beans.xml"/>
</flow>
Manage-Beans.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean class="com.dproductions.test.Service.SiteService" id="SiteService" />
<bean class="com.dproductions.test.Service.CustomerService" id="CustomerService" />
<bean class="com.dproductions.test.Service.UserService" id="UserService" />
</beans>
When attempting to reach the flow I get the following stacktrace : http: //pastebin.com/QmCXe45Y
Which comes down to the Webflow not being able to access the specified package(s).
But it doesn't give a 'ClassNotFoundException' , which is sort of puzzling to me.
Any suggestion is welcome.
Besides, my servlet-context is found here : Servlet-context
I've been fighting this for over a week now.
Edit
I want to be able to use my beans the way they are used at This Example , at the action states, the beans being picked up/managed directly by Spring MVC .
Do the beans have to be declared (and serializable?) in the applicationcontext ? Using xml-notation ?

If I change the
<set>
towards an
<evaluate expression>
and have the beans defined in the file Manage-Beans.xml , it works.
But that way I have to define the same bean twice, as it is once picked up by the pkg-search annotation, and then in the web-flow it is again.
I'd like to have the beans which are already made.
Spring web flow DOES re-create/instantiate the bean again. You can reference properties, autowire them with beans in the web-flow beans import file, but it's like a new context, unaware of existing beans.
(Using events goes to both flow and normal-context files.)

java.lang.IllegalStateException: Exception occurred rendering view
org.springframework.web.servlet.view.JstlView: unnamed; URL
[/WEB-INF/flows/manage/Userview.jsp]
org.springframework.webflow.mvc.view.AbstractMvcView.render(AbstractMvcView.java:191)
org.springframework.webflow.engine.ViewState.render(ViewState.java:296)
org.springframework.webflow.engine.ViewState.refresh(ViewState.java:243)
org.springframework.webflow.engine.ViewState.resume(ViewState.java:221)
org.springframework.webflow.engine.Flow.resume(Flow.java:545)
org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:258)
org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:183)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:322)
Check the view file location.

Related

Conditionally load a bean in spring boot using xml configuration?

I am using Spring Boot 2.1.
I have some mixed configuration in my project : XML files and java classes with annotations.
We have this current configuration which works :
application.properties :
spring.profiles.active=dev, component1, component2
applicationContext-file.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
profile="component1">
<beans>
<bean id="myserviceimpl"
class="org.blabla.MyServiceImpl">
<property name="mydao">
<ref bean="mydao"></ref>
</property>
</bean>
</beans>
</beans>
We want to extract the component values from the spring.profiles.active property since they have nothing to do with the environment :
application.properties :
spring.profiles.active=dev
component1=true
component2=true
How can i condition the instantiation of the myserviceimpl bean inside the applicationContext-file.xml ?
I can no longer rely on the profile attribute since the spring.profiles.active property no longer includes
the values of the components.
Thanks for helping.
I haven't tried it by myself but I suggest to check the following:
Step 1
Create one XML file per profile (say, dev and prod for the sake of example):
app-config-dev.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
profile="dev">
<beans>
<!-- here define only beans that you want to load in __dev__ environment -->
<bean id="myserviceimpl"
class="org.blabla.MyServiceImpl">
<property name="mydao">
<ref bean="mydao"></ref>
</property>
</bean>
</beans>
</beans>
app-config-prod.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
profile="prod">
<beans>
<!-- here define only beans that you want to load in __production__ environment -->
<bean id="myserviceimpl"
class="org.blabla.MyServiceProdImpl">
<property name="mydao">
<ref bean="mydao"></ref>
</property>
</bean>
</beans>
</beans>
Step 2
Now in your "primary" applicationContext-file.xml instead of defining beans directly, include all the xml files that you've created during the step 1:
<import resource="classpath:app-config-dev.xml" />
<import resource="classpath:app-config-prod.xml" />
Read this thread for more details on this step if needed
Step 3
Remove the component1=true and component2=true from aplication properties, you don't need it anymore, the profile itself defines which beans should be loaded.
Update 1
Based OP's first comment:
You probably can try another option but I consider it a "low-level" solution and it requires deep understanding of how does spring loading process work under the hood.
So when spring starts it finds the definitions of beans (in xml, java config, annotations like #Component and so forth) and creates out of all this information a BeanDefinition - a metadata object that aggregates all the information about the bean (for example whether its singleton or prototype). At this point no beans are not created yet. Lets call this point in time a "Bean Definitions Done" point" (for the sake of explanations, its my term out of my head...
Then spring starts to build a graph of dependencies and starts creating beans, initializing them (Autowiring, post-construct methods, and so on) and placing them onto application context (if they're singletons).
Now, in spring there is an option to provide a hook called BeanFactoryPostProcessor that is invoked exactly at the "Bean Definitions Done" point. This is basically a java code that implements some interface and by itself is a spring bean that spring treats in a special way.
So you can implement this interface and manipulate the results of Bean factory.
Namely you can access every bean definition that spring has opened and if you think that the bean of this definition should not be created (here comes your custom logic that would check properties, whatever) - remove the bean definition from the registry:
For technical method of removing bean definitions see this thread
Here is an example of Bean Factory Post processor that actually adds a new bean although it wasn't registered

What happens behind the scenes when a property placeholder is defined in a Spring context (JNDI-wise)?

I have a Java web application using Spring and JSF, deployed in Tomcat.
For the record, in web.xml, only the Faces servlet is configured; there is no Spring servlet.
The entry point to my Spring context is applicationContext.xml, which looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<context:component-scan base-package="my.pack" annotation-config="true" />
<context:property-placeholder location="file:${admin.config.path}/database.properties"/>
<context:spring-configured />
<context:annotation-config />
<aop:aspectj-autoproxy />
</beans>
In the property-placeholder definition one can see that I'm injecting an external property, which, in this case, is an environment variable. This property is passed via Tomcat context configuration, like this:
<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/cntxt">
<Environment name="admin.config.path" value="d:/conf/"
type="java.lang.String" override="false"/>
</Context>
I'm also injecting this environment variable in one of my Spring-managed beans, like this:
#Value("${java:comp/env/admin.config.path}")
private String confDir;
(This is because I'm also using that directory for some other configuration files, which are not .properties files).
With the configuration above, everything works just fine - all the wirings are performed without any flaw.
But, at some moment, I stopped needing injecting properties via the property placeholder configurer from database.properties (but I still need the other files from the admin.config.path), therefore I removed the <context:property-placeholder> line from applicationContext.xml.
At that moment, the injection using #Value stopped working in my Spring-managed bean.
Does anybody know what actually happened? It seems like the JNDI injection fails if the property placeholder configurer is not defined in the Spring context.
Is there any way I can re-enable this kind of injection (without defining a dummy property placeholder pointing to an empty properties file)?
You need a property placeholder configurer instance, the sole purpose of it is to replace placeholders with actual values. If you remove it no placeholders will be replaced.
Either add a <context:property-placeholder /> and leave out the location field or add a bean of the type PropertySourcesPlaceholderConfigurer. Either way will re-enable your placeholder support.
Small suggestion remove the java:comp/env part of the property, by default it will do a JNDI lookup if the property cannot be resolved in other locations (servlet context, properties, system properties etc.).

Spring Webflow 2.3.0 Samples unstartable... No Idea how to fix

I'm currently evaluating Spring (with a focus on WebFlow) for future projects. After reading lots of docs and articles (most of which didn't help much) I downloaded the current release of Spring WebFlow (2.3.0 at the time of writing) and tried to get the samples running. Apart from solvable, yet frustrating, dependency- and classpath-issues, I hit the first roadblock with the config-files distributed with the samples. First of all, the webflow-config.xml of the booking-mvc-sample isn't even valid.
<?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:webflow="http://www.springframework.org/schema/webflow-config"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config.xsd">
<!-- Executes flows: the entry point into the Spring Web Flow system -->
<webflow:flow-executor id="flowExecutor">
<webflow:flow-execution-listeners>
<webflow:listener ref="securityFlowExecutionListener" />
</webflow:flow-execution-listeners>
</webflow:flow-executor>
<!-- The registry of executable flow definitions -->
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices" base-path="/WEB-INF">
<webflow:flow-location-pattern value="/**/*-flow.xml" />
</webflow:flow-registry>
<!-- Plugs in a custom creator for Web Flow views -->
<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator"
development="true" validator="validator" />
<!-- Configures Web Flow to use Tiles to create views for rendering; Tiles allows for applying consistent layouts to your views -->
<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="tilesViewResolver"/>
<property name="useSpringBeanBinding" value="true" />
</bean>
<!-- Installs a listener to apply Spring Security authorities -->
<bean id="securityFlowExecutionListener" class="org.springframework.webflow.security.SecurityFlowExecutionListener" />
<!-- Bootstraps JSR-303 validation and exposes it through Spring's Validator interface -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
</beans>
cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'webflow:flow-executor'.
cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'webflow:flow-registry'.
cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'webflow:flow-builder-services'.
Changing http://www.springframework.org/schema/webflow-config/spring-webflow-config.xsd to http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd removes the validation errors from Eclipse but the SAXParser still complains at startup.
Is there any way around it? Can someone help me out with a working config or point to a working tutorial (either a correct one if it's the samples fault or one that shown me how to setup SWF correctly if I'm doing it wrong)?
Right now I'm not far from dumping SWF from our list of possible frameworks as "not running out of the box" and - looking at the userbase and prevalence of Spring, this is somehow hard to believe.
Thanks a lot.

Spring and JMS Integration Configuration file error

I keep having this error when I'm trying to integrate Spring JMS into my current project. It's driving me up the wall and I'm not entirely sure how to fix it as I'm new to Spring.
The prefix "jms" for element "jms:listener-container" is not bound.
The code in question is this,
<jms:listener-container container-type="default" connection-factory="connectionFactory" acknowledge="auto">
<jms:listener destination="TESTQUEUE" ref="simpleMessageListener" method="onMessage" />
</jms:listener-container>
I'm pretty sure it has to do with the jms: namespace but I don't know how to fix it as before my program was complaining about the p: namespace so I had to change it to property name="some value" reference="someReference"
Make sure you have the jms namespace in your context file:
<?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:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd">
<!-- <bean/> definitions here -->
</beans>
See http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jms.html for details.

Spring MVC annotation error "No adapter for handler - Does your handler implement a supported interface like Controller?"

I have an existing Spring MVC apps written in 2.5.
I wanted to use the new annotation controller. I somewhat see that it is really flexible and would answer my other needs.
My problem is, it seems I cannot mix them both.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan
base-package="com.test.web" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<!-- Controller Mappings Here -->
<bean id="homeController" class="com.test.web.HomeController">
<property name="cacheSeconds" value="120" />
</bean>
//other plain old spring mvc controller
When I ran my app and hit the home page, I get below error:
javax.servlet.ServletException: No adapter for handler [com.test.web.HomeController#cca07b]: Does your handler implement a supported interface like Controller?
I am not sure but I think something is conflicting. This is a fairly large Spring MVC apps and I don't want to change those modules that were working already using the old Spring Base Controller.
My goal is to only use the annotation controller on my new enhancement.
You don't need to declare DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter. The context has these registered by default, along with adapters for old-style controllers.
When you declare them explicitly like this, the default ones are removed, and the context will only support the ones you declare.

Categories

Resources