I'm trying to implement a file upload in my Spring application based on the Spring documentation. However, when I add the SimpleUrlHandlerMapping reference, I can't even route to my login page.
In my web.xml, I have all .htm files mapped to my servlet:
<servlet-mapping>
<servlet-name>myapp</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
then, in myapp-servlet.xml, I have this:
<bean name="/login.htm" class="com.example.web.LoginFormController">
<property name="sessionForm" value="true" />
<property name="commandName" value="loginCommand" />
<property name="commandClass" value="com.example.command.LoginCommand" />
<property name="authenticationService" ref="authenticationService" />
<property name="loginDataAccess" ref="loginDAO" />
<property name="validator" ref="loginValidator" />
<property name="formView" value="login" />
<property name="successView" value="hello.htm" />
</bean>
This allows me to go to the login page and login. However, when I add the following based on the documentation, I get this error: No mapping found for HTTP request with URI [/myapp/login.htm] in DispatcherServlet with name 'myapp'
These are the lines I added to the myapp-servlet.xml file:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>/upload.form=fileUploadController</value>
</property>
</bean>
<bean id="fileUploadController" class="com.example.web.FileUploadController">
<property name="commandClass" value="com.example.domain.FileUploadBean" />
<property name="formView" value="fileuploadform" />
<property name="successView" value="hello.htm" />
</bean>
If I take out the urlMapping section, I can navigate to the upload page, but then I get an IllegalStateException. How do I have Spring route the htm files normally and allow me to upload a file? Shouldn't the urlMapping only matter when the upload.form is called?
Update
Per SKaffman's answer, I updated the myapp-servlet.xml to look like this:
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/upload.form=fileUploadController
/upload.htm=fileUploadController
/login.htm=loginController
</value>
</property>
</bean>
This allows me to navigate to the upload page, but when I click on the submit button, I get a 404 for upload.form saying "(/myapp/upload.form) is not available." If I take the upload.htm out of the mapping, I can't navigate to that page. I don't know what mapping to use for both the page and the upload. The upload page has this action defined:
<form method="post" action="upload.form" enctype="multipart/form-data">
By default, Spring registers multiple HandlerMapping beans automatically, including a BeanNameUrlHandlerMapping. This handler allows you to use things like <bean name="/login.htm"> without any additional configuration.
However, as soon as you add an explicit handler mapping bean, like your SimpleUrlHandlerMapping, then the default ones are no longer registered, and your login controller will not longer be mapped.
The simplest solution for you is probably to add your login controller to the SimpleUrlMappingHandler:
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>/login.htm=loginController</value>
<value>/upload.form=fileUploadController</value>
</property>
</bean>
<bean id=loginController" class="com.example.web.LoginFormController">
...
</bean>
Related
We used to have the following configuration to customize our message converters in Spring 4:
<mvc:annotation-driven conversion-service="conversionService" content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="myObjectMapper"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
But after migrating to Spring 5, the above configuration has lost any effect (the default message converters take place).
If I define the bean explicitly, it works:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="objectMapper" ref="myObjectMapper" />
</bean>
</property>
</bean>
<bean class="org.springframework.http.converter.ByteArrayHttannotation-drivenpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
</list>
</property>
</bean>
Any idea why the mvc:message-converters tag stopped working?
ps. While debugging the issue I also noticed several instances of RequestMappingHandlerAdapter being instantiated in all cases, even though I would expect them to be a singleton. The latter significantly obscures debugging, since I'm not sure which is the right one to attribute message converters to to investigate.
pps. Another report of this issue:
https://stackoverflow.com/a/49156186/657723
In this case mvc:message-converters was overridden by another, empty mvc:annotation-driven which happened to be unnoticeably included down the chain of child xml inclusions.
In any case, the major problem was the silent override, which should have better be an error.
I have a web app where i define 2 bean
1 with a singleton scope and one with a request scope.
I need the request scoped bean inside the singleton bean.
So i ended up with this
<bean id="routingDataSource" class="org.ai2l.ifsr.service.multiTenants.RoutingDataSource" scope="request">
<aop:scoped-proxy/>
<property name="targetDataSources" value="#{tenantSpecificDependencyFactory.tenantIdToDataSource}"/>
<!-- <property name="defaultTargetDataSource" ref="parentDataSource"/> -->
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="ifsrPU"/>
<property name="dataSource" ref="routingDataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="${hibernate.dialect}"/>
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.ejb.naming_strategy">
org.hibernate.cfg.ImprovedNamingStrategy
</prop>
</props>
</property>
</bean>
As you will notice i've use the <aop:scoped-proxy/>but it isn't working.
I've also tryed the
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
inside my web.xml. But none of this is working.
I still get this error
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Does any one know why this happens??
I have an application that runs inside of Websphere, and I am having an issue with persisting JPA entities.
Previously, the application was setup with RESOURCE_LOCAL persistence units, with the Spring JpaTransactionManager, and transactions that were committed explicitly in code.
TransactionStatus transactionStatus = transactionManager.getTransaction( new DefaultTransactionDefinition() );
try {
entityManager.persist( someJpaEntity );
}
catch( Exception exception ) {
transactionManager.rollback( transactionStatus );
throw exception;
}
try {
transactionManager.commit( transactionStatus );
}
catch( TransactionException exception ) {
exception
}
I am working on an enhancement to the application that will allow calls through a Message Driven Pojo linked to a Websphere Queue. I was able to setup a configuration through spring that will allow my application to receive messages through a JMS queue. The spring config looks like:
<jee:jndi-lookup id="jmsConnectionFactory" jndi-name="QueueConnectionFactory"/>
<jee:jndi-lookup id="jmsQueue" jndi-name="DIQueue" />
<!-- A dynamic resolver -->
<bean id="jmsDestResolver" class="org.springframework.jms.support.destination.DynamicDestinationResolver"/>
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref bean="jmsConnectionFactory"/>
</property>
<property name="destinationResolver">
<ref bean="jmsDestResolver"/>
</property>
</bean>
<bean id="messageListener" class="my.app.FileMessageListener" />
<bean id="exListener" class="my.app.JmsExceptionListener" />
<bean id="msgListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory" />
<property name="destination" ref="jmsQueue" />
<property name="messageListener" ref="messageListener" />
<property name="transactionManager" ref="transactionManager" />
<property name="taskExecutor" ref="myTaskExecutor" />
<property name="exceptionListener" ref="exListener" />
</bean>
<bean id="myTaskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName" value="wm/default" />
</bean>
Not sure if there is an issue with my spring setup, but I do receive messages through my Active MQ broker, so that part I seem to be good with.
Now, the issue is, that when I get a message in through JMS, I would call the above code to insert the JPA entity. When the code would run, I would get the message "unable to commit a one phase resource in a two phase transaction", or something similar. What I came to understand is that the Spring JpaTransactionManager does not work with XA or JTA transactions.
So, I worked on moving to the Spring JtaTransactionManager.
I changed everything I Could think of over to use JTA, here is where I declare my transaction manager:
<bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
Updated my persistence XML:
<persistence-unit name="AppUnit" transaction-type="JTA">
<provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
<jta-data-source>java:APPDS</jta-data-source>
And still, nothing works. My code runs without exception, but nothing gets persisted to the database. The message gets pulled off of the JMS Queue, but no data.
Any suggestions?
I finally got this working, and figured I would post the answer.
There are actually 2 pieces to the puzzle.
First, in Websphere, you need to go to your app server -> TransactionService, and check / enable the "Accept Heuristic Hazard" checkbox. That definitely helped. I am running WAS 7.
The second thing, is you MUST set the property eclipselink.target-server on your persistence unit or your EntityManagerFactory.
That second item definitely did the trick. I tested with the property and without it. Without it, nothing persists. With it, everything works fine.
Here is my EntityManagerFactory, I am using a property placeholder to set the value of the eclipselink.target-server property:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="MyUnit" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="databasePlatform">
<value>${app.databasePlatform}</value>
</property>
<property name="showSql">
<value>${app.showSql}</value>
</property>
</bean>
</property>
<!-- THIS DID THE TRICK -->
<property name="jpaPropertyMap">
<map>
<entry key="eclipselink.target-server" value="${app.targetServer}"/>
</map>
</property>
</bean>
I want an interceptor to be called for all the url's with pattern /user/display/* and don't want to configure the controller name to which these url's map to.
Spring documentation gives the following example
<bean id="handlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="officeHoursInterceptor"/>
</list>
</property>
<property name="mappings">
<value>
/user/display/*=editAccountFormController
</value>
</property>
</bean>
In my case i don't want to give editAccountFormController.
Is it possible to do that?
You can specify interceptors independently of the controllers using <mvc:interceptors>, e.g.
<mvc:interceptors>
<mvc:interceptor>
<mapping path="/user/display/*"/>
<bean class="com.x.y.MyInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
See docs for more detail.
greetings all
i am using velocity templates when sending emails
and i want to read texts dynamically from property files depending on user locale
the xml config:
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:messages</value>
<value>classpath:messages_ar</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
<bean id="velocityEngine"
class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<props>
<prop key="resource.loader">class</prop>
<prop key="class.resource.loader.class">org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader</prop>
<prop key="velocimacro.library">org/springframework/web/servlet/view/velocity/spring.vm</prop>
</props>
</property>
</bean>
<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath" value="/WEB-INF/classes/com/spacerdv/mailTemplates"/>
</bean>
<!--
View resolvers can also be configured with ResourceBundles or XML files. If you need
different view resolving based on Locale, you have to use the resource bundle resolver.
-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".vm"/>
<!-- if you want to use the Spring Velocity macros, set this property to true -->
<property name="exposeSpringMacroHelpers" value="true"/>
</bean>
and when trying to read the text from property file like :
<span>#springMessage("hi.message")</span>
it doesn't read any thing, or prints the default value, just prints:
$springMacroRequestContext.getMessage($code)
i don't know why? , am i missing something ?, any help ?
When using the velocity engine for sending emails, you may have to configure your engine tu use the velocimacro librabry shipped within spring.
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<props>
<prop key="resource.loader">class</prop>
<prop key="class.resource.loader.class">org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader</prop>
<prop key="velocimacro.library">org/springframework/web/servlet/view/velocity/spring.vm</prop>
</props>
</property>
</bean>
You can check the example in spring documentation.
If Spring doesn't inject automatically the $springMacroRequestContext variable into your model, you should put it yourself:
model.put("springMacroRequestContext", new RequestContext(request, response, getServletContext(), model));
That's basically what they do in the AbstractTemplateView class. I guess you won't be able to do it, since you're handling emails here, and not web requests. But that's definitely a hint on what you can do to get it working.
macros can't be used outside web app like in email templates, so a solution would be to pass messageSource to the vm file and read from the property file by it like the answer in here:
Is it possible to read static text dynamically from property files in velocity template?