I'm getting a FileNotFoundException when I try to read a properties file in in my spring controller.
Here is the log that shows when and where it occurs:
java.io.FileNotFoundException: src\main\webapp\WEB-INF\props\configFile.properties (The system cannot find the file specified)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at com.webclaims.translator.Translator.readPropertiesFile(Translator.java:65)
at com.webclaims.translator.Translator.createEditablePage(Translator.java:45)
at com.webclaims.translator.controllers.TestController.editableWebpage(TestController.java:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
The location of my properties file is src/main/webapp/WEB-INF/props/configFile.properties
Here is the controller that has the editableWebpage() that is showed in the log:
#RequestMapping(value = "/edit")
public ModelAndView editableWebpage() throws IOException {
final String source = "http://localhost:8080/translator/test";
final String target = "src/main/webapp/WEB-INF/jsp/editable_webpage.jsp";
final String config = "src/main/webapp/WEB-INF/props/configFile.properties";
Translator t = new Translator();
t.createEditablePage(source, target, config);
return new ModelAndView("editable_webpage");
}
Then we go to my Java class that has the createEditablePage() that is seen in the log above:
#PropertySource(value = "configFile.properties")
public class Translator {
#Autowired
private Properties properties;
private static final Logger LOGGER = Logger.getLogger(Translator.class.getName());
public Translator() {
this.properties = new Properties();
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void createEditablePage(String source, String target, String config) {
File file = new File(target);
try {
Document doc = Jsoup.connect(source).get();
Elements elements = doc.select("*");
readPropertiesFile(config);
for(Element element : elements) {
if(!element.ownText().equals("")) {
String key = getKeyFromPropertiesFile(element.text().toString());
if(!key.equals("")) {
element.addClass(key);
element.attr("contentEditable", "true");
}
}
}
FileUtils.writeStringToFile(file, doc.outerHtml(), "UTF-8");
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "IOException has occured", e);
}
}
private void readPropertiesFile(String config) {
try {
File propsFile = new File(config);
FileInputStream inputStream = new FileInputStream(propsFile);
properties.load(inputStream);
inputStream.close();
} catch(FileNotFoundException e) {
LOGGER.log(Level.SEVERE, "FileNotFoundException has occured", e);
} catch(IOException e) {
LOGGER.log(Level.SEVERE, "IOException has occured", e);
}
}
Here is what I have in my web.xml:
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<display-name>translator</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value>
</context-param>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
My spring-servlet.xml contains two bean where one of them is telling spring about the properties 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:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<mvc:annotation-driven/>
<context:component-scan base-package="com.webclaims.*" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean id="propertiesFile" class="com.webclaims.translator.Translator">
<property name="properties" value="/WEB-INF/props/configFile.properties"></property>
</bean>
Your locations are mismatched!
In value attribute you specified value="/WEB-INF/props/configFile.properties"
but you mentioned that your file is at "/WEB-INF/config/configFile.properties"
If you still facing issue try to put property file in src folder
try this..
value="src/main/webapp/WEB-INF/props/configFile.properties"
Oups, there are some misunderstanding of key concepts here...
The location of my properties file is src/main/webapp/WEB-INF/props/configFile.properties. No. This is the location of the source of your property file. You have a build pass that will build a .war file, and that war file will be runned by a servlet container. At that moment (run time) all reference to source files have been lost.
The build process will (broadly speaking and assuming a maven build):
compile all java files to class files and put them under /WEB-INF/classes
copy all files from src/main/resources under /WEB-INF/classes where they will be accessible at run time as resources with ClassLoader.getResource or ClassLoader.getResourceAsStream
copy all files from src/main/webapp directly under / and will be accessible at run time as resources with ServletContext.getResource or ServletContext.getResourceAsStream.
Using resources for read-only data is better, because you can transparently use resources that lives in the META-INF/resources folder of a jar deployed inside your application.
Anyway, if you really need to open a file of the web application, the only correct way is to use the method ServletContext.getRealPath to translate a path relative to the root of the application into an absolute path on the server (and no longer in the developper's source)
So to read the property file, you should get it as a ressource from the ServletContex:
in you controller use the relative path and get the InputStream:
#RequestMapping(value = "/edit")
public ModelAndView editableWebpage(ServletRequest request) throws IOException {
final String source = "http://localhost:8080/translator/test";
final String config = "/WEB-INF/props/configFile.properties";
...
InputStream inputStreamConfig = request.getServletContext()
.getResourceAsStream(config);
t.createEditablePage(source, target, inputStreamConfig);
return new ModelAndView("editable_webpage");
}
in the readPropertiesFile method, just load the properties:
properties.load(inputStreamConfig);
But there are other problems is your code:
in Translator class you have both:
#Autowired
private Properties properties;
meaning that properties should be injected, and
public Translator() {
this.properties = new Properties();
}
initializing it in constructor. One is useless.
The Translator class uses Autowired annotation so it should be a Spring bean, but you create it with new. Do not do that but inject it in the controller
In web.xml, you declare the same file for the root context and for the DispatcherServlet context => every bean will be created twice, once in each context. But you did not declare any ContextLoaderListener to bootstrap Spring. It is common to find this:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Related
I have a Tomcat Server and I'm trying to access the index.html file located in the WEB-INF folder, as shown in the picture below
As seen in the picture, when I open http://localhost:9999/index.html it throws a 404
This is my web.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="CERTHMaTHiSiSOpenAPI" version="3.1">
<display-name></display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>OpenAPI</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
api.ws;api.ws.oper
</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
<param-value>api.ws.oper.Authorization</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>OpenAPI</servlet-name>
<url-pattern>/api/*</url-pattern>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
</web-app>
Is it a problem that it's located under WEB-INF/lib? I tried moving it to WEB-INF with no success.
Edit: This is my Properties > Web Project Settings Tab:
It should be noted that this project has also an API, and under Java Resources > src > ws it has a Conductor.java file with this content:
package ws;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import io.swagger.jaxrs.config.BeanConfig;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;
import io.swagger.models.Swagger;
import io.swagger.util.Json;
import ws.util.Config;
#ApplicationPath("/")
public class Conductor extends Application {
#Context ServletContext context;
public static Properties properties = new Properties();
public Conductor() {
super();
BeanConfig beanConfig = new BeanConfig();
BeanConfig beanConfig2 = new BeanConfig();
beanConfig.setVersion("3.1.1");
beanConfig.setSchemes(new String[]{"https","http"});
// beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/api");
beanConfig.setResourcePackage("ws.lg");
beanConfig.setTitle("LG lib Open API");
beanConfig.setScan(true);
Swagger swaglg = new Swagger();
swaglg = beanConfig.getSwagger();
swaglg.setBasePath("/api/lg");
beanConfig2.setVersion("3.1.1");
beanConfig2.setSchemes(new String[]{"https","http"});
// beanConfig.setHost("localhost:8080");
beanConfig2.setBasePath("/api");
beanConfig2.setResourcePackage("ws.sla");
beanConfig2.setTitle("SLA lib Open API");
beanConfig2.setScan(true);
Swagger swaglg2 = new Swagger();
swaglg2 = beanConfig2.getSwagger();
swaglg2.setBasePath("/api/sla");
createSwaggerJsonFile(beanConfig, "swagger-lg.json");
createSwaggerJsonFile(beanConfig2, "swagger-sla.json");
}
// public static final int REST_PORT = 8080;
#Override
public Set<Class<?>> getClasses(){
readProperties();
Set<Class<?>> resources = new HashSet<>();
addRestResourceClasses(resources);
return resources;
}
private void addRestResourceClasses(Set<Class<?>> resources){
resources.add(ws.sla.SLAlibOpenAPI.class);
resources.add(ws.lg.LGlibOpenAPI.class);
resources.add(ws.auth.Authorization.class);
resources.add(ApiListingResource.class);
resources.add(SwaggerSerializers.class);
//to turn off
// resources.add(ws.helpers.MongoModifiersAPI.class);
}
private Properties readProperties() {
String fullPath = context.getRealPath(Config.PROPERTIES_FILE);
InputStream inputStream = null;
try {
inputStream = new FileInputStream(new File(fullPath));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
if (inputStream != null) {
try {
properties.load(inputStream);
} catch (IOException e) {
// TODO Add your custom fail-over code here
e.printStackTrace();
}
}else{
System.err.println("Cannot read config file or no config file exists.");
}
return properties;
}
// /*
private static void createSwaggerJsonFile(BeanConfig beanConfig, String filename) {
try (FileWriter fileWriter = new FileWriter(filename)) {
File f = new File(filename);
fileWriter.write(Json.pretty(beanConfig.getSwagger()));
fileWriter.flush();
System.out.println("File " + filename + " successfully created in " + f.getAbsolutePath());
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
// */
}
You should place your html content inside WebContent folder, not inside web-inf. As it searches the index.html in WebContent and its not there so its showing 404 not found error.
Have a look at this question having similar situation and possible answer
StackOverFlow Question
The solution was to move all the swagger-ui files to a new folder under WebContent (which I called ui), to move the web.xml to WEB-INF and to add a simple servlet-mapping inside web.xml:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/ui/*</url-pattern>
</servlet-mapping>
the problem was that the /api/* url-pattern in the OpenAPI servlet, was consumed by the API.
I had a similar issue. I was confused between html front pages stored in WebContent, and servlets produced by the Java code.
Tomcat searches for .html files in WebContent, as indicated in Context Parameters. The url-parameter of the servlet mapping tells Tomcat where to look for the servlet itself. To me, it's then logical that both locations needs to be different.
My servlet-mapping looks like <url-pattern>/api/*</url-pattern>. My application class contains #Path('/sname'). While keeping WEB-INF/web.xmlas simple as possible, this gives me access to html pages at localhost:8080/ and to servlets at localhost:8080/api/sname.
By default, ROOT war index.html(or welcome-file-list) will be called when you try to access using http://localhost:9999/index.html
If you want to change tomcat default loading page then edit server.xml file and update the following
<Context path="" docBase="new_default_app" />
Use jdk 1.8
SpringMVC-4.3.3
SpringCore-4.3.3
javax.servlet-api-3.0.1
spring-data-jpa:1.10.4
hibernate-entitymanager:4.2.5.Final
hibernate-core:4.2.5.Final
Simple Logging Facade for Java:1.6.1
I encountered with such error
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name
'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping':
Invocation of init method failed; nested exception is
java.lang.NoSuchMethodError:
org.springframework.core.annotation.AnnotatedElementUtils.hasAnnotation
My question:
Why error encoured and how fix it?
web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>product</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>product</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
product-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<context:component-scan base-package="com.kopylov.spring.controller" />
<mvc:annotation-driven/>
Controller
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class ProductController {
#RequestMapping
public String showHome(){
return "home";
}
}
AppInitializer
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses(){
return new Class<?>[]{
DataConfig.class
};
}
#Override
protected Class<?>[] getServletConfigClasses(){
return new Class<?>[0];
}
#Override
protected String[] getServletMappings(){
return new String[0];
}
}
DataConfig
#Configuration
#EnableTransactionManagement
#ComponentScan("com.kopylov.spring")
#PropertySource("classpath:/com/kopylov/spring/resources/app.properties")
#EnableJpaRepositories("com.kopylov.spring.repository")
public class DataConfig {
private static final String PROP_DATABASE_DRIVER = "db.driver";
private static final String PROP_DATABASE_PASSWORD = "db.password";
private static final String PROP_DATABASE_URL = "db.url";
private static final String PROP_DATABASE_USERNAME = "db.username";
private static final String PROP_HIBERNATE_DIALECT = "db.hibernate.dialect";
private static final String PROP_HIBERNATE_SHOW_SQL = "db.hibernate.dialect";
private static final String PROP_ENTITYMANAGER_PACKAGES_TO_SCAN = "db.entitymanager.packages.to.scan";
private static final String PROP_HIBERNATE_HBM2DDL_AUTO = "db.hibernate.hbm2ddl.auto";
#Resource
private Environment env;
#Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROP_DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(PROP_DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(PROP_DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty(PROP_DATABASE_PASSWORD));
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
emfb.setDataSource(dataSource());
emfb.setPersistenceProviderClass(HibernatePersistence.class);
emfb.setPackagesToScan(env.getRequiredProperty(PROP_ENTITYMANAGER_PACKAGES_TO_SCAN));
emfb.setJpaProperties(getHibernateProperties());
return emfb;
}
#Bean
public JpaTransactionManager transactionManager(){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
private Properties getHibernateProperties(){
Properties properties = new Properties();
properties.put(PROP_HIBERNATE_DIALECT, env.getRequiredProperty(PROP_HIBERNATE_DIALECT));
properties.put(PROP_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROP_HIBERNATE_SHOW_SQL));
properties.put(PROP_HIBERNATE_HBM2DDL_AUTO, env.getRequiredProperty(PROP_HIBERNATE_HBM2DDL_AUTO));
return properties;
}
Perfect solution worked for me :
Add commons-configuration-1.6.jar to the lib directory
Probably you have forgot to import your product-servlet to configuration class
you could move your product-servlet.xml to 'resources' so that it is available in classpath
so your servlet mapping looks like this
<servlet>
<servlet-name>product</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/product-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>product</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
in your config class
#Configuration
#EnableTransactionManagement
#ComponentScan("com.kopylov.spring")
#PropertySource("classpath:/com/kopylov/spring/resources/app.properties")
#EnableJpaRepositories("com.kopylov.spring.repository")
#ImportResource("classpath:/product-servlet.xml")
public class DataConfig {
//..
}
BTW, better not to mix match xml and java configuration. As java config has become norm, you could use WebMvcConfigurerAdapter
http://www.mkyong.com/spring-mvc/gradle-spring-4-mvc-hello-world-example-annotation/
First clean your project and build again. Check whether you are getting this error.
Then Check with this: nested exception is java.lang.NoSuchMethodError:
org.springframework.core.annotation.AnnotatedElementUtils.hasAnnotation
I think you have missed some repositories in pom.xml or multiple jars of different versions in your pom.xml. Sometimes your spring jars not match mutually with each other.
Add this:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
Remove 4.3.3.RELEASE from all spring dependencies.
Refer: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/overview.html (Read: Maven "Bill Of Materials" Dependency)
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependencies>
I dont think your dispatcher is configured correctly in your web.xml. You do not have any <init-param> tags. See docs
http://docs.spring.io/spring-flex/docs/1.0.x/reference/html/ch02s02.html
Try editing to:
<servlet>
<servlet-name>product</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/product-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
EDIT for additional info
Also, I believe you will need to add some mapping to your #RequestMapping annotation, see link:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping
First check if all of the build path errors are resolved or not.
In most of this kind of cases spring initializer throws this error if build path errors are not resolved.
I'm making a simple project for school but I'm stuck.
I have a bean FavoriteService that I need to address. However when autowiring the bean in my servlet I keep getting a Null Pointer Exception and I can't figure out why.
FavoriteService
public class FavoriteService {
#Autowired
private Users users;
public boolean checkLogin(String username, String password) {
return users.login(username, password);
}
public void addUser(String rootUsername, String rootPassword, String username, String password)
{
if(rootUsername.equals("root") && rootPassword.equals("rootpasswd")) users.addUser(username, password);
}
public List<String> getFavorites(String username, String password)
{
List<String> favorites;
if(checkLogin(username, password))
{
favorites = users.getFavorites(username);
} else {
favorites = new ArrayList<String>();
}
return favorites;
}
public void addFavorite(String username, String password, String favorite)
{
if(checkLogin(username, password))
{
users.addFavorite(username, favorite);
}
}
public void removeFavorite(String username, String password, String favorite)
{
if(checkLogin(username, password))
{
users.removeFavorite(username, favorite);
}
}
}
Servlet
public class LoginServlet extends HttpServlet {
#Autowired
private FavoriteService favoriteService;
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(favoriteService);
if(favoriteService.checkLogin(username, password))
{
resp.sendRedirect("root.jsp");
} else {
resp.sendRedirect("index.jsp");
}
}
}
springservlet-servlet
<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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="be.kdg.prog4.tdd"/>
<bean name="userDao" class="be.kdg.prog4.tdd.UserDaoWithMap" scope="singleton" />
<bean name="users" class="be.kdg.prog4.tdd.Users" scope="singleton" />
<bean name="favoriteService" class="be.kdg.prog4.tdd.FavoriteService" scope="singleton" />
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".*"/>
</bean>
</beans>
Web.xml
<web-app schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>TDD oefening</display-name>
<servlet>
<servlet-name>springservlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springservlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Login</servlet-name>
<servlet-class>be.kdg.prog4.tdd.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Login</servlet-name>
<url-pattern>/LoginServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
If you need any more info feel free to ask.
Thanks.
EDIT:
I solved it by doing this in the servlet init
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext());
}
If you are calling LoginServlet you are not going through Spring. You mapped it directly in your web.xml and your set let container is initializing your class without going through Spring and the autowired does not work. You need the access the server through a mapping of springservlet.
The Servlet is not initialized by Spring and therefore the #Autowired fields are not getting initialized by Spring.
Instead of using #Autowired you can override the Servlet init() method and get the Spring web context and use its getBean method to get your bean.
This is how you can get the Spring context in your init method:
ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
I have a Spring Controller with several RequestMappings for different URIs. My servlet is "ui". The servlet's base URI only works with a trailing slash. I would like my users to not have to enter the trailing slash.
This URI works:
http://localhost/myapp/ui/
This one does not:
http://localhost/myapp/ui
It gives me a HTTP Status 404 message.
The servlet and mapping from my web.xml are:
<servlet>
<servlet-name>ui</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ui</servlet-name>
<url-pattern>/ui/*</url-pattern>
</servlet-mapping>
My Controller:
#Controller
public class UiRootController {
#RequestMapping(value={"","/"})
public ModelAndView mainPage() {
DataModel model = initModel();
model.setView("intro");
return new ModelAndView("main", "model", model);
}
#RequestMapping(value={"/other"})
public ModelAndView otherPage() {
DataModel model = initModel();
model.setView("otherPage");
return new ModelAndView("other", "model", model);
}
}
Using Springboot, my app could reply both with and without trailing slash by setting #RequestMapping's "value" option to the empty string:
#RestController
#RequestMapping("/some")
public class SomeController {
// value = "/" (default) ,
// would limit valid url to that with trailing slash.
#RequestMapping(value = "", method = RequestMethod.GET)
public Collection<Student> getAllStudents() {
String msg = "getting all Students";
out.println(msg);
return StudentService.getAllStudents();
}
}
If your web application exists in the web server's webapps directory, for example webapps/myapp/ then the root of this application context can be accessed at http://localhost:8080/myapp/ assuming the default Tomcat port. This should work with or without the trailing slash, I think by default - certainly that is the case in Jetty v8.1.5
Once you hit /myapp the Spring DispatcherServlet takes over, routing requests to the <servlet-name> as configured in your web.xml, which in your case is /ui/*.
The DispatcherServlet then routes all requests from http://localhost/myapp/ui/ to the #Controllers.
In the Controller itself you can use #RequestMapping(value = "/*") for the mainPage() method, which will result in both http://localhost/myapp/ui/ and http://localhost/myapp/ui being routed to mainPage().
Note: you should also be using Spring >= v3.0.3 due to SPR-7064
For completeness, here are the files I tested this with:
src/main/java/controllers/UIRootController.java
package controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class UiRootController {
#RequestMapping(value = "/*")
public ModelAndView mainPage() {
return new ModelAndView("index");
}
#RequestMapping(value={"/other"})
public ModelAndView otherPage() {
return new ModelAndView("other");
}
}
WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0" metadata-complete="false">
<servlet>
<servlet-name>ui</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<!-- spring automatically discovers /WEB-INF/<servlet-name>-servlet.xml -->
</servlet>
<servlet-mapping>
<servlet-name>ui</servlet-name>
<url-pattern>/ui/*</url-pattern>
</servlet-mapping>
</web-app>
WEB-INF/ui-servlet.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="controllers" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:order="2"
p:viewClass="org.springframework.web.servlet.view.JstlView"
p:prefix="/WEB-INF/views/"
p:suffix=".jsp"/>
</beans>
And also 2 JSP files at WEB-INF/views/index.jsp and WEB-INF/views/other.jsp.
Result:
http://localhost/myapp/ -> directory listing
http://localhost/myapp/ui and http://localhost/myapp/ui/ -> index.jsp
http://localhost/myapp/ui/other and http://localhost/myapp/ui/other/ -> other.jsp
Hope this helps!
PathMatchConfigurer api allows you to configure various settings
related to URL mapping and path matching. As per the latest version of spring, trail path matching is enabled by default. For customization, check the below example.
For Java-based configuration
#Configuration
#EnableWebMvc
public class AppConfig extends WebMvcConfigurerAdapter {
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseTrailingSlashMatch(true);
}
}
For XML-based configuration
<mvc:annotation-driven>
<mvc:path-matching trailing-slash="true"/>
</mvc:annotation-driven>
For #RequestMapping("/foo"), if trailing slash match set to false, example.com/foo/ != example.com/foo and if it's set to true (default), example.com/foo/ == example.com/foo
Cheers!
I eventually added a new RequestMapping to redirect the /ui requests to /ui/.
Also removed the empty string mapping from the mainPage's RequestMapping.
No edit required to web.xml.
Ended up with something like this in my controller:
#RequestMapping(value="/ui")
public ModelAndView redirectToMainPage() {
return new ModelAndView("redirect:/ui/");
}
#RequestMapping(value="/")
public ModelAndView mainPage() {
DataModel model = initModel();
model.setView("intro");
return new ModelAndView("main", "model", model);
}
#RequestMapping(value={"/other"})
public ModelAndView otherPage() {
DataModel model = initModel();
model.setView("otherPage");
return new ModelAndView("other", "model", model);
}
Now the URL http://myhost/myapp/ui redirects to http://myhost/myapp/ui/ and then my controller displays the introductory page.
Another solution I found is to not give the request mapping for mainPage() a value:
#RequestMapping
public ModelAndView mainPage() {
DataModel model = initModel();
model.setView("intro");
return new ModelAndView("main", "model", model);
}
try adding
#RequestMapping(method = RequestMethod.GET)
public String list() {
return "redirect:/strategy/list";
}
the result:
#RequestMapping(value = "/strategy")
public class StrategyController {
static Logger logger = LoggerFactory.getLogger(StrategyController.class);
#Autowired
private StrategyService strategyService;
#Autowired
private MessageSource messageSource;
#RequestMapping(method = RequestMethod.GET)
public String list() {
return "redirect:/strategy/list";
}
#RequestMapping(value = {"/", "/list"}, method = RequestMethod.GET)
public String listOfStrategies(Model model) {
logger.info("IN: Strategy/list-GET");
List<Strategy> strategies = strategyService.getStrategies();
model.addAttribute("strategies", strategies);
// if there was an error in /add, we do not want to overwrite
// the existing strategy object containing the errors.
if (!model.containsAttribute("strategy")) {
logger.info("Adding Strategy object to model");
Strategy strategy = new Strategy();
model.addAttribute("strategy", strategy);
}
return "strategy-list";
}
** credits:
Advanced #RequestMapping tricks – Controller root and URI Template
Not sure if this is the ideal approach, but what worked for me was to treat them as if they were two different paths and make them both accepted by each of my endpoints, such as.
#RestController
#RequestMapping("/api/mb/actor")
public class ActorController {
#GetMapping({"", "/"})
public ResponseEntity<Object> getAllActors() {
...
}
#GetMapping({"/{actorId}", "/{actorId}/"})
public ResponseEntity<Object> getActor(#PathVariable UUID actorId) {
...
}
There may be best ways to do this and to avoid this duplication, and I'd love to know that. However, what I found when I tried using configurer.setUseTrailingSlashMatch(true); is that broken paths also start becoming accepted, such as /api/mb////actor (with many slashs), and that's why I ended up going the multiple paths instead.
I start learn AOP with spring framework 3.1.2. But I have trouble. In Beans.xml context file i wrote:
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<bean id = "audience" class="com.MySpring.Audience"></bean>
<aop:config>
<aop:aspect ref="audience">
<aop:pointcut id="performance" expression="execution(* com.MySpring.Performer.perform(..))"/>
<aop:before pointcut-ref="performance" method="seatDown"/>
<aop:before pointcut-ref="performance" method="turnOffPhone"/>
<aop:after-returning pointcut-ref="performance" method="applauz"/>
<aop:after-throwing pointcut-ref="performance" method="demandRefund"/>
</aop:aspect>
</aop:config>
</beans>
And Java class
public class AOPTest {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext context = new ClassPathXmlApplicationContext(
"Beans.xml");
}
}
// ///
class Audience {
public void seatDown() {
out.println("Seat down");
}
public void turnOffPhone() {
out.println("Turn Off Phone");
}
public void applauz() {
out.println("Aplauz");
}
public void demandRefund() {
out.println("We have money back");
}
}
////
interface Performer{
void perform();
}
But in error console i see:
Description Resource Path Location Type
Error occured processing XML 'class path resource [org/aopalliance/aop/Advice.class] cannot be opened because it does not exist'. See Error Log for more details Beans.xml /AnnotationsWiring/src line 11 Spring Beans Problem
And second error:
Description Resource Path Location Type
Error occured processing XML 'org/springframework/aop/aspectj/AspectJMethodBeforeAdvice'. See Error Log for more details Beans.xml /AOP/src line 12 Spring Beans Problem
I guess you are learning spring using examples from spring in action. In fact, you are missing a com.springsource.org.apoalliance.jar file, which is not included in org.springframework.aop.jar(though i don't know why).
Please download it at: http://sourceforge.net/projects/aopalliance/files/aopalliance/
You have the Caused by: java.lang.ClassNotFoundException: org.aopalliance.aop.Advice because you don't include the jar into your classpath.