I'm developing an application in JSP using SimpleFormController with Spring MVC 3.0.2 using Hibernate. Everything is fine. I'm also using Validator to validate forms on the server side. It's also going on well.
Now, I need to use Ajax as an example, when a country is selected from a drop down (<form:select><form:option></form:option></form:select>), the states corresponding to that country should be populated from the database in the state drop down.
I have done such things using Ajax in places but yet not with Spring MVC. I have gone through many tutorials/articles about SimpleFormController on Google but none of them were using Ajax. I couldn't find a single idea about how to use Ajax with SimpleFormController.
With annotated controllers (#Controller), the thing can be made easy because methods can be mapped using the #RequestMapping annotation (nevertheless I haven't yet used it but I think I can).
But with SimpleFormController, I don't have any precise idea about how to handle Ajax requests in the Spring controller (which methods to be mapped and how). With SimpleFormController, I'm usually associated with the onSubmit(), showForm() and referenceData() methods.
Could you please expose some thoughts on how can an Ajax request be made on SimpleFormController, which methods can be mapped and how? (I don't want the full code anymore. A very simple example (if and only if it's possible) or furthermore specific links where the use of Ajax with the SimpleFormController is explained would be quite enough for me to study).
You could always just have a separate #Controller to handle the ajax requests. If you can have custom jsp on the view, there is nothing stopping you from handling an ajax request on the page. Just bind the onchange event of the select box to an ajax call pointing to the other Controller you made.
In terms of keeping it bound to just that SimpleFormController, I don't think this is possible, but if you create a new RESTful controller that the form would use, other parts of the website will be able to use this new controller as well.
In complement to dardo's answer, using both spring MVC 2 and MVC 3 controllers is possible, but a bit tricky to set up.
In order to use both SimpleFormController and #Controller controllers in the same Spring context, I used to following definition :
<!-- ======== MVC Spring 3.x ======== -->
<!-- Scans within the base package of the application for #Components to configure as beans #Controller, #Service, #Configuration, etc. -->
<context:component-scan base-package="com.your.package" />
<!-- Enables the Spring MVC #Controller programming model -->
<!-- It's a shortcut equivalent to the (more complete) bean definition below (see bean AnnotationMethodHandlerAdapter).-->
<!--<mvc:annotation-driven />-->
<!-- This HandlerAdapter will register spring 3.x controllers (#Controller) into the DispatcherServlet -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<array>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="writeAcceptCharset" value="false"/>
</bean>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
</array>
</property>
</bean>
<!-- This HandlerMapping allows to map urls defined in #RequestMapping annotations to the corresponding controllers -->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
</bean>
<!-- ======== MVC Spring 2.x ======== -->
<!-- This HandlerAdapter will register spring 2.x controllers (#Controller) into the DispatcherServlet -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!-- Url mapper -->
<bean id="urlMapper" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/foo.do" value-ref="fooController" />
<entry key="/bar.do" value-ref="barController" />
...
</map>
</property>
</bean>
Related
I'm currently working with legacy code and I wanna read some properties from the Environment. I know this would be easily done using spring boot with:
#Autowired
Environment environment;
But, since I'm wiring all the components using an application-context.xml file, I don't know how to wire the Environment there,
<bean name="myBean" class="com.acme.MyClass">
???
</bean>
Thanks for your help #volveira89 #rmlan
Using the xml file, this is working:
<bean name="myBean" class="com.acme.MyClass">
<constructor-arg ref="environment"/>
</bean>
It seems that you have no experience in Spring XML config. You should look at this example by Spring team: https://spring.io/blog/2011/01/04/green-beans-getting-started-with-spring-mvc/
You need something like this in your application-context.xml:
<!-- Scans within the base package of the application for #Components
to configure as beans -->
<!-- #Controller, #Service, #Configuration, etc. -->
<context:component-scan base-package="xyz.sample.baremvc" />
<!-- Enables the Spring MVC #Controller programming model -->
<mvc:annotation-driven />
Now your,
#Autowired
Environment environment
should work!
I want to make an interceptor that will intercept every request except a few ones. The problem that I have is the interceptor still intercepts the requests that I provided with exclude-mapping. I tried all sorts of variations but nothing worked. Here is the configuration
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/checkout/campaign/**"/>
<bean class="com.package.package.package.package.package.CampaignBeforeControllerHandler" >
<-- list of services -->
</bean>
</mvc:interceptor>
And here is an actual request: https://localhost:9002/checkout/campaign/test . In my opnion the pattern matches this request so it should be excluded but it is not, I still get into the class of the interceptor. Is the pattern that I provided somehow bad?
EDIT: I am using Spring MVC 3.2.8
probably you have adding 'mvc' to inner elements that causes
Doc example
<mvc:interceptors>
<mvc:interceptor>
<mapping path="/**"/>
<exclude-mapping path="/checkout/campaign/**"/>
<bean class="com.package.package.package.package.package.CampaignBeforeControllerHandler" >
<-- list of services -->
</bean>
</mvc:interceptor>
</mvc:interceptors>
Spring configuration file creates beans and interconnects them. Is this correct? I have a chain of beans in my application but want to test it with smaller chains. Can I have multiple chains defined with Spring? Or only one bean structure is allowed?
EXAMPLE
Suppose this is production config:
<bean id="provider"
class="tests.Provider">
</bean>
<bean id="processor1" class="tests.Processor1">
<property name="input" ref="provider"/>
</bean>
<bean id="processor2" class="tests.Processor2">
<property name="input" ref="processor1"/>
</bean>
<bean id="consumer" class="tests.Consumer">
<property name="input" ref="processor2"/>
</bean>
And I want to test in the following configs:
<bean id="provider"
class="tests.Provider">
</bean>
<bean id="analyzer" class="tests.Analyzer">
<property name="input" ref="provider"/>
</bean>
And:
<bean id="provider"
class="tests.Provider">
</bean>
<bean id="processor1" class="tests.Processor1">
<property name="input" ref="provider"/>
</bean>
<bean id="analyzer" class="tests.Analyzer">
<property name="input" ref="processor1"/>
</bean>
And so on, attaching beans one by one.
Yes, you can.
You can break overall configuration of Spring application context for your application into parts (XML files if you use XML configuration, packages with #Components if you use classpath scanning, #Configurations if you use Java-based configuration) and construct an application context using a subset of these parts.
So, if your application has two features foo and bar, you can declare beans used by these features in foo.xml and bar.xml respectively (if you use XML configuration), and import them from the main configuration of your application (such as applicationContext.xml).
Now, if you want to write integration test for bar you can create application context from bar.xml only (#ContextConfiguration("bar.xml")). Obviously, you should take care of interdependencies between different parts of your configuration. For example, if both foo.xml and bar.xml depend on beans declared in db.xml, you may want to create something like test-db.xml and configure your integration test for bar as #ContextConfiguration({"bar.xml", "test-db.xml"}).
Note that this approach requres some discipline, especially if you use classpath scanning - in this case parts of your configuration are defined by packages, therefore you need to follow "package by feature, not by layer" rule.
See also:
9.3 Integration testing
I believe you want to test for integration, what I usually do is to separate my bean configuration files in tiers and then import them as needed for testing. Something like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<context:property-placeholder
location="classpath:mx/gob/jgtjo/apps/schedule/web/schedule-web.properties"
file-encoding="UTF-8" system-properties-mode="NEVER" />
<!-- Context files -->
<import resource="spring/dataContext.xml" />
<import resource="spring/serviceContext.xml" />
<import resource="spring/securityContext.xml" />
<import resource="spring/components.xml" />
</beans>
And then, if I need to test for Daos, I only import the dataContext.xml inside a testContextDao.
In simple terms spring framework takes care of Object Creation. These objects you want Spring to manage you define them as beans. So when spring creates a bean1 if that bean1 has reference to bean2, the bean2 is instantiated and injected to bean1 and finally bean1 is created. Thinking of it as chain will be over complicating.
Section 3.2 of spring docs
In a webapplication I am using different components which are all using Spring 3.0.x having their own DataSource and TransactionManager (all with different names). They are all included in the context via the "main" webapp via including their spring config.
<import resource="classpath:spring-config-componentName.xml" />
In each of the Spring configs of the components I am using declarative transaction management, enabled via
<tx:annotation-driven transaction-manager="transactionManager_componentName" />
And for each method that should be transactional I add a annotation that looks like this:
#Transactional(propagation=Propagation.REQUIRES_NEW, value="transactionManager_componentName")
The problem I have is that I found out that only one TransactionInterceptor is created which has a reference to one of the transactionManagers but not of the one of the component itself. Is there a way to handle this? Like to specify a TransactionInterceptor as a bean and then reference it in the #Transactional annotation?
I think there is a possibility by specifying a TransactionProxyFactoryBean in each component and doing the declarative transaciton management via the xml config. But this is something I would like to avoid.
The proposed way as described in the Spring docs (10.5.6.2 Multiple Transaction Managers with #Transactional) does not work.
Finally I found out what the problem was and I have to say that it works as it is described in the spring docs.
If you are using more than one TransactionManagerin your Spring Container and you are using #Transactionit does not work if you are specifiying the TransactionManager like this:
<tx:annotation-driven transaction-manager="transactionManager_componentName" />
All you have to do ist to remove the specification of the TransactionManager and use a configuration like this:
<!-- ========== ENABLE ANNOTATIONS ========== -->
<tx:annotation-driven/>
<!-- ========== TRANSACTION MANAGER ========== -->
<bean id="transactionManager_component1"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource_component1" />
<property name="nestedTransactionAllowed" value="true" />
<qualifier value="component1"/>
</bean>
And for you methods you want to run in a transaction then just specify it like this:
#Transactional(value="component1")
Using Spring 3.0.2.RELEASE. I'm having 2 Controllers in package com.myCompany. The Controllers are activated via Component-scan
<context:component-scan base-package="com.myCompany" />
then I'm having a interceptor bind to the 2 controllers via
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="myInterceptor"/>
</list>
</property>
</bean>
How can i bind the interceptor to only one specific Controller or to only certain methods inside a Controller?
Background: I want to inspect the URL that it contains certain parameters
Docu Link
When you inject interceptors into a HandlerMapping bean, those interceptors apply to every handler mapped by that HandlerMapping. That was fine in the pre-annotation days, since you'd just have configure multiple HandlerMapping beans. However, with annotations, we tend to have a single DefaultAnnotationHandlerMapping that maps everything, so this model doesn't work.
The solution is to use <mvc:interceptors>, where you explicitly map paths to interceptor beans. See the docs, and this example:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/secure/*"/>
<bean class="org.example.SecurityInterceptor" />
</mvc:interceptor>
</mvc:interceptors>