I am using default configuration of Spring MVC 2. So, my dispatcher will look like,
<prop key="index.htm">indexController</prop>
I have a simple htm file on root. When I browse this file I get 404:Not Found Error. How to browse (which exist physically on disk) htm file in Spring MVC.
In annotation based Spring 3.x, you can just write it in your controller as,
#RequestMaping(value="/index.htm")
public void doSomeJob(){
//some code here
}
and if you make a request as "/pathToIt/index.htm", then it will be caught by doSomeJob() method..
P.S No need for request mappings in configuration files in Spring MVC 3.x
Note: And also 404 can be caused if spring can't find your physical file..
Try and add a bean id in your springmvc-servlet.xml file :
<bean id="indexController" class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
then :
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
...
<prop key="/index.htm">indexController</prop>
</props>
</property>
</bean>
Ok this sounds familiar , if you are using MVC 2 then the best way to achieve this is to give a specific mapping for dispatcher servlet instead of /
<servlet>
<servlet-name>myDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>myDispatcherServlet</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
This will make sure the only requests to *.jsp will go dispatcher servet and rest will be handled by the container itself.
You need to map URL index.htm with your controller. You cannot view your page until it will have correct spring mvc configuration.
<bean name="/index.htm" class="com.indexController">
....
</bean>
In controller you will pass your jsp page name as view in modelAndView.
Check your view resolver has correct setting like this
<!-- View Resolver -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix">
<value>/WEB-INF/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
Related
I am working on a project where we decided to add some interaction using jms and hornetq as provider.
I am quite new to Camel so I ran into a problem some if you may refer as trivial.
The goal was to initialize connection factory and add the jms component. However, as I understand it can't be done directly in the route configurator. So I created camel-config.xml and placed it to the resources/ directory.
I filled it in the following way:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
<prop key="java.naming.provider.url">jnp://localhost:1099</prop>
<prop key="java.naming.factory.url.pkgs">org.jnp.interfaces:org.jboss.naming</prop>
</props>
</property>
</bean>
<bean id="jmsQueueConnectionFactory"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>ConnectionFactory</value>
</property>
</bean>
<bean name="jms" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="jmsQueueConnectionFactory"/>
</bean>
</beans>
The project doesn't use Spring so it was the only example of the xml I have found that doesn't make use of Spring.
In the route configurator I use routeBuilder.from("jms:queue:top").to("...");
However, when I start the project it throws FailedToCreateEndpointException and states
"No component found with schema: jms".
I suppose that the xml file is simply not used but I just can't understand how to point to it.
Looking forward to hearing any advice.
The <beans/> XML is a Spring configuration that has to be bootstrapped in some way. You may have a look at the Tomcat ActiveMQ example found here, showing how to do that in a servlet environment. Have a special look at web.xml:
<!-- location of spring XML files -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:broker.xml,
classpath:camel-config.xml
</param-value>
</context-param>
<!-- the listener that kick-starts Spring, which loads the XML files and start our application -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Of course, you could also use a Java only setup as follows:
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
ModelCamelContext context = new DefaultCamelContext();
context.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
I'm trying to upload a multipart file using Ajax, Spring MVC 3.2.0, Tomcat 8.0.9, but can't get it work. I read a lot of blogs and similar posting here on stackoverflow (Spring upload file problems, MultipartConfig with Servlet 3.0 on Spring MVC, …) which seem to have similar causes but couldn't figure out how to solve it. The weird thing is that the upload works when the file is smaller than 1MB, but when ever the recorded video exceeds that size, the following error is raised:
org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. null
org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:163)
org.springframework.web.multipart.commons.CommonsMultipartResolver.resolveMultipart(CommonsMultipartResolver.java:139)
org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:110)
In the following you can see all the configurations I made:
The AJAX POST-Request:
var videoBlob = e.data;
var pathArray = window.location.pathname.split( '/' );
var userID;
for (i = 0; i < pathArray.length; i++) {
if (pathArray[i].toString() == "edit"){
userID = pathArray[i+1];
}
}
var fd = new FormData();
fd.append('fname', 'video');
fd.append('data', videoBlob);
$.ajax({
url: '/user/edit/uploadVideo/' + userID,
data: fd,
processData: false,
contentType: false,
type: 'POST',
success: function(data)
{
$('#result').html(data + "uploaded by FormData!");
}
});
The web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:root-context.xml</param-value>
</context-param>
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>common</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<display-name>springMultipartFilter</display-name>
<filter-name>springMultipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>springMultipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The servlet-context.xml
<mvc:annotation-driven />
<mvc:resources mapping="/**" location="/resources/" />
<context:component-scan base-package="de.talentwuerfel"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/schema"/>
<property name="username" value="root"/>
<property name="password" value=""/>
<property name="validationQuery" value="SELECT 1"/>
</bean>
<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="packagesToScan">
<array>
<value>de.talentwuerfel</value>
</array>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
The root-context.xml where I defined the MultipartResolver
<bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000000"/>
<property name="maxInMemorySize" value="4096"/>
</bean>
The Java-Controller
#RequestMapping(value = "/edit/uploadVideo/{id}", method = RequestMethod.POST)
public #ResponseBody String uploadVideo(#PathVariable long id, MultipartHttpServletRequest request, HttpServletResponse response) throws IOException {
//.... file handling
}
How can I solve this problem?
EDIT:
I tried the suggested approach and used the Servlet implementation to manage my video-file upload. The following adjustments have been made, but it's still resulting in a similar error:
Adjusted #Controller:
#RequestMapping(value = "/edit/uploadVideo/{id}", method = RequestMethod.POST)
public String uploadVideo(#PathVariable long id, #RequestParam("data") Part file) {
//...
}
The root-controller has been deleted and I added the multipartResolver to the servlet-context.xml
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</bean>
The tag was in the web.xml has been extended by the following Multipart-Configuration:
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<multipart-config>
<location>/tmp</location>
<max-file-size>20848820</max-file-size>
<max-request-size>418018841</max-request-size>
<file-size-threshold>1048576</file-size-threshold>
</multipart-config>
</servlet>
However, I'm still getting an exception and can't upload a blob file larger than 1MB:
Could not parse multipart servlet request; nested exception is java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. null
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:927)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:822)
javax.servlet.http.HttpServlet.service(HttpServlet.java:644)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796)
javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
I implemented a similar file upload where a single file was simply picked and it totally worked to send large files while using the same configuration. So I believe it has rather something to do with the Ajax POST or the attached blob file?!
you can add this in you application to active Servlet3.0 MultiParsing:
#Bean
public MultipartConfigElement multipartConfigElement() {
MultiPartConfigFactory factory = new MultiPartConfigFactory();
factory.setMaxFileSize("128KB");
factory.setMaxRequestSize("128KB");
return factory.createMultipartConfig();
}
or do it in XML.
Not really an answer to your exact question, just my 2 cents. There are basically 2 ways of uploading files with the help of Spring MVC :
using Jakarta Commons FileUpload, the only way (aside from implementing one yourself) before the appearance of the servlet 3.0 API
using the Servlet implementation of your server (only if servlet impl version >= 3.0)
Since you are using Tomcat 8.0.9, the Servet 3.0 option is available to you which I definitely recommend since it doesn't introduce yet another external dependency in your project. Also, since it follows the Servlet 3.0 spec, the configuration of such upload mechanism is now java standard which is nice in case you decide to move from Spring MVC to another MVC framework (your configuration values would remain the same).
In case you can't figure out your IOFileUploadException, I think you should give it a try.
I read this "It is a best practice to keep a clear separation between middle-tier services such as business logic components and data access classes (that are typically defined in the ApplicationContext) and web- related components such as controllers and view resolvers (that are defined in the WebApplicationContext per Dispatcher Servlet)."
And decide configure my application like that 4 separate xml file
applicationContext.xml
<context:component-scan base-package="appname">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
dao.xml
<!-- MySQL JDBC Data Source-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://#{mysqlDbCredentials.hostname}:#{mysqlDbCredentials.port}/#{mysqlDbCredentials.name}"/>
<property name="username" value="#{mysqlDbCredentials.username}"/>
<property name="password" value="#{mysqlDbCredentials.password}"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="JpaPersistenceUnit" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.showSql">true</prop>
</props>
</property>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager"
id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
and mvc-dispatcher-servlet.xml
<mvc:annotation-driven />
<context:component-scan base-package="appname" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
web.xml(load spring context)
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/mvc-dispatcher-servlet.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/spring/*</url-pattern>
</servlet-mapping>
<!-- Load spring beans definition files -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/applicationContext.xml
/WEB-INF/spring/security.xml
/WEB-INF/spring/dao.xml
</param-value>
</context-param>
But I'm absolutly confused.
1)I don't understand how many context in this case I get.
2)I want easy replace tx mode on aspectj (which work just in ome context as I know). But when I replace I get error with transation.
Main problem that I want to have universal variant for both type of transaction
Here I add mode="aspectj" and I have annotation like #Service, #Resourse, on concrete classes
<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj" proxy-target-class="true"/>
All seems should work but I get next exception on flush
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:948)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:575)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1239)
at [internal classes]
at org.apache.logging.log4j.core.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:66)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:194)
at [internal classes]
Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:993)
at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
Please, help me uderstand better
convention is you have one root context, normally applicationContext.xml. Then different servlet contexts (for different modules/functionality)... myapp-servlet.xml.
The servlet context can see everything in root context, but not the other way. Controllers and webby stuff(static resources) go in servlet context, everything else (eg service, and security) go in root context.
You can import different files as you please. But define those two contexts in your web.xml (or Java conf equivalent).
I still do it the old fashioned xml way, you don't have to use java conf.
Whats your actual error ?
I've got a spring-security setup in my web-app. I want to replace some messages of spring security with my custom messages i.e.
Instead of Bad Credentials I want AbstractUserDetailsAuthenticationProvider.badCredentials to have value invalid username or password, please try again
This is my spring setup :
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/messages/messages"/>
<!-- Tried this as well <property name="basename" value="/WEB-INF/messages/messages.properties"/> -->
<property name="cacheSeconds" value="0" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
And I have created folder in the WEB-INF called messages. Inside this folder there is file called messages.properties. Inside this file is one line :
AbstractUserDetailsAuthenticationProvider.badCredentials=invalid username or password, please try again
What am I doing wrong here?
Update :
This servlet-context is defined in the web xml :
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Problem solved, moved the messageSource bean definition to another context.
Everything looks right. Try to get the message using spring message tag in order to check if the problem is with your configuration or with the security message:
<spring:message code="AbstractUserDetailsAuthenticationProvider.badCredentials" />
If this does work, problem is not with your configuration (that looks fine for me).
Anyway, try to put your messages files in the classpath (source folder) and this:
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages/messages"/>
<property name="cacheSeconds" value="0" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
Also, check that the bean is being declared in a application context file that Spring is aware of.
I'm using Spring 3 and i don't know how to map somepage.htm to somepage.jsp without a controller.
That is: if i go to somepage.htm, i want it to show me the jsp. But of course without redirect. I dontw want anyone to see ".jsp" only ".htm"
<servlet>
<servlet-name>Training01</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Training01</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
The way to do is to use the <mvc:view-controller..> tag in combination with a view resolver.
See here for more documentation:
The <mvc:view-controller..> tag maps urls to views. So if you want to map the relative url /login to a view names login you would do it by adding the following line to you webmvc-context.xml file:
<mvc:view-controller path="/login" view-name="login" />
Of course to get this to work you'll have to have a view resolve - something that maps logic names to specific views - setup in your context. In your case since you are using straight jsps for you view layer you'll want to add something like this to your configuration:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
So with this setup if you had a jsp login.jsp located in you /WEB-INF/jsp directory then you would be able to directly reference that jsp from the url www.myapp.com/mycontenxtroot/login
See here for some more info on view resolvers:
You might be interested in UrlRewriteFilter. This is the approach I would recommend. If you're serious about clean URLs you'll likely need it at some point anyway.
On the other hand, if it's a one-off, a minimal controller might be easier:
#Controller
public class Somepage {
#RequestMapping("/somepage")
public String handler() {
return "somepage.jsp";
}
}