How do I access file in WEB-INF in JSP? - java

I am using Tomcat. I would like to put the config file in WEB-INF instead of the default root class path which is WEB-INF/classes. Currently I put the config.xml in WEB-INF and use the following relative addressing to locate it:
InputStream input = Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream("..//config.xml");
Is this the correct way to do?
Or should I use the getServletContext().getRealPath("config.xml") first? But I don't know how to obtain the getServletContext() in a .java. (I tried to new HttpServlet for obtaining getServletContext(), but since it is an abstract class, can't be instanced... how can I get the getServletContext()?)

The method getRealPath() is not guaranteed to work, e.g. if your webapp is not expanded from a war file there is no 'real path' on the filesystem to a file inside the war file.
Since you say you are using a ServletContextListener, you can get the ServletContext out of the ServletContextEvent:
sce.getServletContext().getResourceAsStream("/WEB-INF/config.xml");

You can use getServletConfig() method return an instance of ServletConfig.
ServletContext sc=getServletConfig().getServletContext();
EDIT:
public void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException{
ServletContext sc=getServletContext();
...
}

Related

Get the Path of a resource from a spring boot aplication using servlet context

I have this structure, generated by spring boot
So I want to get a input stream of the file gastos.xlsx using sevletContext.
#Autowired
private ServletContext context;
#GetMapping("/grafico")
public ResponseEntity<String> exportExcelGrafico(HttpServletResponse response){
try{
//this path returns null. What is the real path to put here?
InputStream input = context.getResourceAsStream("src/main/resources/templates/gastos.xlsx");
//returns null
input = context.getResourceAsStream("/resources/templates/gastos.xlsx");
// Returns null
input = context.getResourceAsStream("/templates/gastos.xlsx");
}
catch(){
}
What would be the right path?
I didn't configure anything on my application.properties
What's in the src/main/resources folder of your Maven or Gradle project ends up in your jar, not in the web resources. And it should thus be loaded using the class loader, not using the servlet context:
MyClass.class.getResourceAsStream("/templates/gastos.xlsx")
Not sure why you put that file under templates, since... it's not a template.

Redirect correctly to a JSP inside WEB-INF

I am a but stuck and confused over this. I have all my .JSP files inside WEB-INF/pages/ and want to access them.
I have done a requestDispatcher on /forward/* like this
#WebServlet("/forward/*")
public class ForwardController extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/WEB-INF" + req.getPathInfo()).forward(req, resp);
}
}
This works great and I can access my JSP files using /forward/pages/index.jsp, though, what I have read so should this not be accessable for the user, but now it clearly is. Is this done in the right way?
Also, now that we've redirect to that link, http://localhost/forward/pages/index.jsp
and want to logout, i use a button to /logout, but now the link before follows along like this, http://localhost/forward/pages/logout
How can I overcome these 2 things?
Best regards
As said the jsp pages inside WEB-INF can only be accessible through controller so whenever you need to access any jsp from another jsp then you need to route through controller. If you want to access jsp to jsp then those should be outside WEB-INF

How to reach the WebContent folder from a web service method

I want to reach a file in WebContent folder from a method in a web service in the same project. For example:
#WebMethod
public String test() {
File configFile = new File("config.xml");
return configFile.getAbsolutePath();
}
It returns "/usr/share/glassfish3/glassfish/domains/domain1/config/config.xml". I want to get to a file in the directory "/usr/share/glassfish3/glassfish/domains/domain1/applications/my_project_name/" folder. How can I get to it?
The best way to do this that I use is:
Thread.currentThread().getContextClassLoader().getResource("myFile.txt").getPath()
This gives the path of any file myFile.txt placed in /WEB-INF/classes/ directory inside the WebContent folder of the WebApp.
In Eclipse JEE environment you need to keep the file myFile.txt, that you may want to read within the Web Service, in the src folder for it to be transported to the /WEB-INF/classes/ folder by the deployer.
From your code, I understand that yours is an JAXWS webservice.
In jaxws, you can get the HttpServletRequest, HttpServletResponse, ServletContext,
Have a private variable in your webservice class and annotate it in this way
#Resource
private WebServiceContext context;
And then in your method, you can get the ServletContext this way
ServletContext servletContext =
(ServletContext) context.getMessageContext().get(MessageContext.SERVLET_CONTEXT);
From servletContext, you can get the path.
Suppose if you need to get HttpServletRequest, you can get it in this way
HttpServletRequest request =
(HttpServletRequest) context.getMessageContext().get(MessageContext.SERVLET_REQUEST);
and you can get the context path of your app like
request.getContextPath() ;
Add the following parameter to your web service class:
#Context
ServletContext context;
Then, supposing your config.xml file is in the WebContent folder, you can get its absolute path by invoking the method context.getRealPath(String). Using your example code it would be:
#WebMethod
public String test() {
File configFile = new File(context.getRealPath("config.xml"));
return configFile.getAbsolutePath();
}
Or directly, without passing by a File object:
#WebMethod
public String test() {
return context.getRealPath("config.xml");
}

Best Practice? Where do I put configuration parameters for my own application in Struts2?

In Java servlet, there is <context-param>. In desktop applications, we usually define our own configuration file.
Where should I put configuration parameters for my Struts2 application? For example, my application needs to set a time limit for user input, or save and read files stored somewhere, or the maximum time the user can type a wrong password, etc. I want those things configurable.
What's the way people usually do it in Struts2 applications? Any best practice?
If you are familiar with the ServletContext approach that you mentioned, you can stick with that. In your web.xml, just add your <context-param>s.
Then, to get the ServletContext in your actions, just implement ServletContextAware and it will be automatically injected for you.
Here's a brief example:
web.xml
<context-param>
<param-name>someSetting</param-name>
<param-value>someValue</param-value>
</context-param>
Your Action
public class YourAction extends ActionSupport implements ServletContextAware {
private ServletContext servletContext;
#Override
public String execute() throws Exception {
String someValue = (String) servletContext.getAttribute("someSetting");
return SUCCESS;
}
#Override
public void setServletContext(final ServletContext context) {
this.servletContext = servletContext;
}
}
See here: Apache Struts 2 Documentation - Handling File Uploads
or : Apache Struts 2 Documentation - File Upload
Properties can be set by putting a struts.properties file in WEB-INF/classes. Any property found in the properties file will override the default value.
struts.multipart.parser - This property should be set to a class that extends MultiPartRequest. Currently, the framework ships with the Jakarta FileUpload implementation.
struts.multipart.saveDir - The directory where the uploaded files will be placed. If this property is not set it defaults to javax.servlet.context.tempdir.
struts.multipart.maxSize - The maximum file size in bytes to allow for upload. This helps prevent system abuse by someone uploading lots of large files. The default value is 2 Megabytes and can be set as high as 2 Gigabytes (higher if you want to edit the Pell multipart source but you really need to rethink things if you need to upload files larger then 2 Gigabytes!) If you are uploading more than one file on a form the maxSize applies to the combined total, not the individual file sizes.
If you're happy with the defaults, there is no need to put any of the properties in struts.prop
I typically put all these settings in my struts.properties file located in the default package. They can also be set in the struts.xml file if you use this type of configuration.
A Google search turns up a plethora of file handling examples for struts 2 using "Struts2 file upload" as your search parameters.
I use a config xml document that I load in a class that implements javax.servlet.ServletContextListener class. From there I set attributes to the servletContext:
public void contextInitialized(ServletContextEvent contextEvent) {
try{
Document xmlDocument = readConfigFile(contextEvent.getServletContext().getRealPath("") + fileSeperator + AppConfigConstants.XML_CONFIG_LOCATION);
contextEvent.getServletContext().setAttribute(AppConfigConstants.RECORDS_PAGE_NODE_NAME,this.getValueFromConfig(AppConfigConstants.RECORDS_PAGE_NODE_NAME,xmlDocument));
...
}
Then in my struts base action class I have methods that get the properties from the servlet context.
protected Integer getRecordsPage(){
Integer recordsPage = Integer.valueOf("0");
if(this.getServlet().getServletContext().getAttribute(AppConfigConstants.RECORDS_PAGE_NODE_NAME)!= null){
recordsPage = Integer.valueOf(this.getServlet().getServletContext().getAttribute(AppConfigConstants.RECORDS_PAGE_NODE_NAME).toString());
}
return recordsPage;
}

Wrap the default servlet but override the default webapp path

I have a folder of static html,imgs,flash content that lives outside of the webapp folder. Right now I'm using a symbolic link to map that folder into my webapp directory. The problem i have is when I undeploy my application it follows the symbolic link and deletes all these files.
One of the solutions I'm trying to implement is a special servlet that wraps the default servlet but uses a different relative path. I'm having trouble finding out how to wrap the default servlet in a way that overrides the default servlet path.
Here is what I'm working with:
public void doGet(final HttpServletRequest req, final HttpServletResponse resp)
throws ServletException, IOException {
final RequestDispatcher rd = getServletContext().getNamedDispatcher("default");
final HttpServletRequest wrapped = new HttpServletRequestWrapper(req) {
#Override
public String getServletPath() {
return "/usr/depot/repository";
}
};
rd.forward(wrapped, resp);
}
You can override DefaultServlet with your own implementation. You can perfectly subclass it, it's a public class. Here are the functional specifications of the DefaultServlet, you need to adhere it.
On the other hand you can ignore DefaultServlet and go for your own solution, an example can be found here.
You can either write your own servlet to serve static content (which is not that hard) or try to extend rather than wrap the DefaultServlet. Either way, your resulting servlet will have be configured in place of default in your web.xml (using "default" as servlet-name).
That said, DefaultServlet will only serve static content from under your webapp context; in order to change that you'll have to create / bind to JNDI your own ProxyDirContext instance pointing to the outside folder and I'm not sure whether that will work; its configuration process is rather involved.
Trying to override servlet path will not get you anywhere.
We have a similar problem that we need to share some files generated by CMS among several applications. Symlink is the easiest way to do this if you are not using Windows.
We setup 2 accounts for CMS and Tomcat. The files are read-only to Tomcat so it can't delete them.
You can also write a small Tomcat extension so it can look for files in multiple places. See this web site,
http://blog.bazoud.com/post/2009/05/12/Multiples-docbases-avec-tomcat
Your current approach won't work. Tomcat needs to load up all the resources in a cache on deploy for it to be available. It's too late to change that in request processing. This extension allows Tomcat load resources from multiple directories. The drawback of this approach is that you have to put a small JAR in server/lib.
That's not a good idea.
Web containers or application servers can be deployed behind Web servers or you can simply use a Web server in conjunction with your container. Just put your static files under that and refer to them by absolute path.
There's really no need for this kind of hack (sorry but that's what it is).
Either that or simply deploy them with the Web app.
You can change to a different path within your webapp context. Here's an example which does differential serving depending on whether the client's User-Agent supports ES6:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
RequestDispatcher rd = getServletContext().getNamedDispatcher("default");
HttpServletRequest wrapped = new HttpServletRequestWrapper(req) {
#Override
public String getServletPath() {
String prefix = supportsES6(req) ? "/es6" : "/es5";
String newPath = prefix + req.getServletPath();
if (newPath.endsWith("/")) newPath += "index.html";
return newPath;
}
};
rd.forward(wrapped, resp);
}
However, "es5" and "es6", even though we use the initial slash, are subdirectories of the webapp's ordinary context. It's not possible to break outside of the context directory using this method.
I have open-sourced a custom servlet that serves files from an arbitrary base path. Additionally, it supports file browsing inside nested compressed archives.
It's available here: https://bitbucket.org/teslamotors/zip-listing/overview

Categories