Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing files/directories in webapp folder in Spring

I'm inexperienced in Spring and everything I need to do now is to access and obtain a reference to files and folders in the webapp folder. Here is my relevant project hierarchy:

-src
--main
---java (marked as source root)
----my
-----package
------controller
-------Home.java
---webapp
----images
-----avatars

My code in Home.java:

@Controller
@RequestMapping("/")
public class Home
{
    @RequestMapping(method = RequestMethod.GET)
    public String index(Model model,
                        HttpServletRequest request) throws Exception
    {
        String test1 = request.getSession().getServletContext().getRealPath("");
        String test2 = request.getSession().getServletContext().getRealPath("/");
        String test3 = request.getRealPath("");
        String test4 = request.getRealPath("/");
        String test5 = request.getSession().getServletContext().getRealPath(request.getServletPath());

        return "index";
    }
}

All the 5 requests return null. Am I doing something wrong?

web.xml:

<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_2_5.xsd"
         version="2.5">

    <display-name>Test</display-name>

    <servlet>
        <servlet-name>test</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>test</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <session-config>
        <session-timeout>10</session-timeout>
    </session-config>
</web-app>

What I'm trying to achieve (not shown in this example), is to code a controller responsible for the scaling of an image. For this reason I would need access to the src/main/webapp/_images folder.

Thank you!

Update: simplified the example for better understanding.

Update2: thanks to the suggestion of @gigadot, I deployed the application as an exploded WAR and the problem is partly solved. Can someone tell me what's the difference in deploying the WAR as exploded? Is it something not recommended to do on a production server? Advantages/disadvantages?

I think it's worth to explain the situation with an example. Let's say I'm coding a social network and I have to possibility to upload my personal profile picture. This picture will be uploaded to the src/main/webapp/_images/avatars/[myid].jpg folder. Is it recommended to upload pictures to the webapp folder? Or is there a better solution? I would like to be able to return a scaled instance of the image when accessing the URL /images/[width]x[height]/[userid].jpg.

Deploying the WAR as exploded and implementing the ResourceLoaderAware (thanks @KevinSchmidt), I can make it work using this:

resourceLoader.getResource("file:" + request.getSession().getServletContext().getRealPath("/") + "_images/avatars/");

To me it looks quite dirty, is it a good idea for a production server? Is there a better solution?

like image 744
satoshi Avatar asked Feb 06 '12 18:02

satoshi


2 Answers

How exactly did you deploy your application?

ServletContext().getRealPath("/") may return null if it is not deployed as exploded. Read the link below for further information. However, the method to configure this may not be the same for your servlet container.

http://ananthkannan.blogspot.com/2009/12/servletcontextgetrealpath-returns-null.html

Updates

Can someone tell me what's the difference in deploying the WAR as exploded?

When you deploy the war file as exploded, the servlet container, e.g. Tomcat, will extract the content of war file into a temporary folder and runs everything from that folder so the {WEB_ROOT]/_images/avatars/[myid].jpg is actually exist on file system (hard disk). Therefore, you can actually get the real path (as it already says in the name of the method). However, if your servlet container does not extract the war file, the folder you are looking for is inside the war file and there is no real path to it so it will return null.

Is it something not recommended to do on a production server? Advantages/disadvantages?

You should not store dynamic contents under your source folder or the webroot folder (webapp) since servlet container will use it temporarily and delete it or change to a new folder when you redeploy your web application. You will likely lost the dynamic data you put into these folders. The web root folder is usually designed for storing static content, which means content you don't want to change - for example, graphic images for your web component like background images, css, etc.

The usual method for storing user data is to somehow create a folder in userspace and put your dynamic data in there. However, you will not be able to serve the content of the folder outside webroot. You will need to write your own static servlet to pipe the data when they are requested. This is quite complicated for a beginner.

The easiest way for implementing your own static servlet to serve dynamic content is to extend the static servlet of your servlet container. However, your code will highly depend on the servlet container you are deploying to.

Since you are going to provide a REST interface for resizing images, you can create a controller which reads in the original images from the dynamic content folder, do the resizing, save it as a temporary file or flush the content of the HttpResponse.

like image 83
gigadot Avatar answered Oct 13 '22 01:10

gigadot


This is my code and it works I dont get null.

I'm running JDK 1.7_02 Tomcat 7.0.25 Spring 3.1.1

And i'm not getting nulls

    @Controller
    public class IndexController {

        @RequestMapping("/index")
        public String go(HttpServletRequest request, HttpServletResponse response) {
            HttpSession session = request.getSession();
            ServletContext sc = session.getServletContext();
            String x = sc.getRealPath("/");
            System.out.println(x);
            return "index";
        }
    }
like image 45
Titi Wangsa Bin Damhore Avatar answered Oct 13 '22 00:10

Titi Wangsa Bin Damhore