I am using the following method to get a resource from WAR file in WildFly:
this.getClass().getResource(relativePath)
It works when the application is deployed as exploded WAR. It used to work with compressed WAR, too. Yesterday, I did a clean and rebuild of project in Eclipse, and it just stopped working.
When I check the resource root:
logger.info(this.getClass().getResource("/").toExternalForm());
I get this:
file:/C:/JBoss/wildfly8.1.0.CR1/modules/system/layers/base/org/jboss/as/ejb3/main/timers/
So, no wonder it doesn't work. It probably has something to do with JBoss module loading, but I don't know if this is a bug or normal behavior.
I found various similar problems on StackOverflow, but no applicable solution. One of the suggestions is to use ServletContext like so:
@Resource
private WebServiceContext wsContext;
...
ServletContext servletContext = (ServletContext)this.wsContext.getMessageContext()
.get(MessageContext.SERVLET_CONTEXT);
servletContext.getResource(resourcePath);
But, when I try to obtain MessageContext in this manner, I get an IllegalStateException. So I am basically stuck. Any ideas?
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;
来源:https://stackoverflow.com/questions/23845031/wildfly-getting-resource-from-war