WildFly - getting resource from WAR

喜欢而已 提交于 2019-11-29 14:46:55

I ran into this same problem, and rather than define the resource as a shared module, I ended up working around this by using a ServletContextListener in my WAR.

In the contextInitialized method, I got the ServletContext from the ServletContextEvent and used its getResource("/WEB-INF/myResource") to get the URL to the resource inside my WAR file. It appears that in the ServletContextListener, the .getResource() method resolves as expected rather than to the "/modules/system/layers/base/org/jboss/as/ejb3/main/timers/" url. That URL can then be stored in the ServletContext for later use by your servlets or in an injected ApplicationScoped CDI bean.

@WebListener
public class ServletInitializer implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        try {
            final ServletContext context = sce.getServletContext();
            final URL resourceUrl = context.getResource("/WEB-INF/myResource");
            context.setAttribute("myResourceURL", resourceUrl);
        } catch (final MalformedURLException e) {
            throw new AssertionError("Resource not available in WAR file", e);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {}
}

or

@WebListener
public class ServletInitializer implements ServletContextListener {

    @Inject
    private SomeApplicationScopedBean myBean;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        try {
            final ServletContext context = sce.getServletContext();
            final URL resourceUrl = context.getResource("/WEB-INF/myResource");
            myBean.setResourceUrl(resourceUrl);
        } catch (final MalformedURLException e) {
            throw new AssertionError("Resource not available in WAR file", e);
        }  
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {}
}

We had a similar problem and our fault was that we tried to access the static resource through the raw path instead of using the input stream the resource is providing - the following code works for us even when deploying a non-exploded .war-file.

final URL resource = this.getClass().getResource(FILE);

try (final InputStream inputStream = resource.openStream();
     final InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
     final BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
    // Use bufferedReader to read the content
} catch (IOException e) {
    // ...
}

I finally gave up and put my resource files in a new JBoss module, as described in this link.

https://community.jboss.org/wiki/HowToPutAnExternalFileInTheClasspath

It works, but the downside is that there are two deployment targets so things are more complicated. On the upside, the size of the WAR file is reduced, and I don't have to redeploy the application if only some of the resources have changed.

I was recently trying to figure out how to access a file within my own war in Java. The following is how the java classes and resources are packaged in the war file:

WAR
 `-- WEB-INF
        `-- classes (where all the java classes are)
        `-- resourcefiles
                   `-- resourceFile1

My target file was resourceFile1. To get that file, I just did the following in code:

InputStream inStream = this.class.getClassLoader().getResourceAsStream("resourcefiles/resourceFile1");

In this case the resource files would need to be in the same folder as the classes folder containing the java classes. Hopefully others find this helpful.

This sample code works for wildfly deployed and tested on openshift. I think it is a wildfly problem I downland wildfly and tried on local I also get the error.

Check sample project on github

import org.springframework.web.bind.annotation.RequestMethod;    
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;

@Controller
@RequestMapping
public class FileDownloadController {

    private static final Logger logger = LoggerFactory.getLogger(FileDownloadController.class);

    private static final String DOC_FILE = "file/ibrahim-karayel.docx";
    private static final String PDF_FILE = "file/ibrahim-karayel.pdf";


    @RequestMapping(value = "/download/{type}", method = RequestMethod.GET)
    public void downloadFile(HttpServletRequest request, HttpServletResponse response,
                             @PathVariable("type") String type) throws IOException {

        File file = null;
        InputStream inputStream;
        if (type.equalsIgnoreCase("doc")) {
            inputStream = getClass().getClassLoader().getResourceAsStream(DOC_FILE);
            file = new File(Thread.currentThread().getContextClassLoader().getResource(DOC_FILE).getFile());
        } else if (type.equalsIgnoreCase("pdf")) {
            inputStream = getClass().getClassLoader().getResourceAsStream(PDF_FILE);
            file = new File(Thread.currentThread().getContextClassLoader().getResource(PDF_FILE).getFile());
        } else{
            throw new FileNotFoundException();
        }
        if (file == null && file.getName() == null) {
            logger.error("File Not Found -> " + file);
            throw new FileNotFoundException();
        }

        String mimeType = URLConnection.guessContentTypeFromName(file.getName());
        if (mimeType == null) {
            System.out.println("mimetype is not detectable, will take default");
            mimeType = "application/octet-stream";
        }

        System.out.println("mimetype : " + mimeType);
        response.setContentType(mimeType);
        /* "Content-Disposition : inline" will show viewable types [like images/text/pdf/anything viewable by browser] right on browser
            while others(zip e.g) will be directly downloaded [may provide save as popup, based on your browser setting.]*/
        response.setHeader("Content-Disposition", String.format("inline; filename=\"" + file.getName() + "\""));

        /* "Content-Disposition : attachment" will be directly download, may provide save as popup, based on your browser setting*/
        //response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName()));

        response.setContentLength(inputStream.available());
        IOUtils.copy(inputStream, response.getOutputStream());
        response.flushBuffer();
        inputStream.close();
    }
}

Had the same issue with Wildfly and not-exploded WAR and using Spring and ServletContextResource I have got around it like this:

[org.springframework.core.io.]Resource resource = new ServletContextResource(servletContext, "WEB-INF/classes/resource.png");

In the same @Service class I also had:

@Inject
private ServletContext servletContext;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!