So I have an Axis2 web service (called "ReleaseService"), which requires a properties file to work correctly. I've deployed axis2 into Tomcat7 on RHEL6 and have a structure like this:
tomcat/webapps/axis2
+ axis2-web, META-INF, org
+ WEB-INF
+ + classes, conf, lib, modules
+ + services
+ + + ReleaseService
+ + + + com, lib, META-INF
Thinking about Java, I would expect the working directory to be tomcat/webapps/axis2/WEB-INF/services/ReleaseService, because it contains a lib folder and the root folder for my binaries.
So I put my properties file in there and tried to access it via
File configFile = new File("releaseservice.properties");
which apparently doesn't work. I've looked for hours but couldn't find a post or documentation snippet, which tells me where the working directory is. I found this, but a system property is no option for me, because I want to keep the deployment simple.
Found out, that the working directory is my tomcat/bin folder, which is the root of the Tomcat Java process.
Bonus question: How can I find out my service directory inside my web service? Does Axis2 provide any helpers to find out which is the folder for the service?
Making assumptions about the current working directory in application code deployed in a Java EE container is not recommended. In addition, you are making the assumption that when the WAR is deployed, releaseservice.properties will exist as a file, i.e. that the container explodes the WAR. This is true for Tomcat, but may not be the case on other servers.
Axis2 creates a distinct class loader for every deployed service. This means that you can access your property file by looking it up as a resource:
MyService.class.getResourceAsStream("/releaseservice.properties")
Replace MyService with the actual class implementing your service, or any other class loaded from WEB-INF/services/ReleaseService.
Apparently the working directory is the tomcat/bin folder. Even though it seems like there is a dedicated application running inside tomcat, it's all the same Java process.
Found it out by adding the following debug code:
File test = new File("abc.txt");
System.out.println(test.getAbsolutePath());
Which returned /opt/tomcat/bin
Related
I'm using Java Spring Boot and deploying to Tomcat 8.1 webapp.
When I create a new File() with a relative path, it is referring to the absolute root of the system.
For instance,
File x = new File("./temp.txt");
System.out.println("X Path: " + x.getAbsolutePath());
The output is
/./temp.txt
Why is this? I'm getting a Java.nio.File.AccessDeniedException because Tomcat does not have permissions to write to the root.
The code is a third party library creating a cache file, so I can't feasibly just change to absolute path.
What causes Tomcat to use / as my working directory?
So I determined the problem. Tomcat, when executed as a service (CentOS: systemctl start tomcat) the WorkingDirectory defaults to root if it is not set.
By editing the tomcat.service file in /etc/systemd/system and adding under the [Service] section the following:
WorkingDirectory=/opt/tomcat
I was able to move the directory where the third party library was writing.
I know this question has answered many a time with most useful answer as below,
Where to place and how to read configuration resource files in servlet based application?
However, We have some special requirement as below,
Webapp will be deployed to tomcat.
Normal java app in form of .jar will be placed under folder /myapp
myappConfig.property file will be placed under /myapp
Directory Structure on client machine
/myapp
/myapp.jar
/assests/myappConfig.property
/tomcat/webapps/myapp.war
Basically myapp.jar and myapp.war will access sql db connection values for MySql database connection and db operations.
Accessing myappConfig.property from myapp.jar --> Working fine
File jarPath = new File(Myapp.class.getProtectionDomain().getCodeSource().getLocation().getPath());
String propertiesPath = jarPath.getParent();
System.out.println(" propertiesPath-" + propertiesPath);
mainProperties.load(new FileInputStream(propertiesPath + "\\assets\\myapp.property"));
Can anyone help/suggest how to implement,
Accessing myappConfig.property file from mywebapp,
provided run time change in myappConfig.property file does not required myapp.war to be redeployed
Thanks for your help in advance.
edit
Below is the steps in which we want to deliver the project to client.
Below is my app directory
/myapp
/myapp.jar
/assests/myappConfig.property
/tomcat/webapps/myapp.war
pack everything in one package with some packaging tool.
Run this package in client machine at any location and it will have same directory structure as above
Here, I do not want to hard code any location in webapp or tomcat for "/assests/myappConfig.property"
Normal Java app I can read property file but for wepapp I am not getting clear idea for how to do that?
You can add a <context> to tomcat/conf/server.xml (in this example, linux path):
<Context docBase="/home/yourusername/tomcat/assests" path="/assets" />
If you are using Windows:
<Context docBase="C:\path\to\myapp\assets" path="/assets" />
And then you can access it like any other resource within your webapp (e.g.: /assets/myappConfig.property).
If you are using JDBC for example, you could store the connection properties in a Singleton and request it from there, and that class could take care of change checks on that file.
I`m developing client that uses library Overthere 2.3.1. With local machine client works perfectly. But when I try to call same code included to EJB 3.0, I've got exception that not all required classes have been loaded.
I`ve looked over the source and found that the class contains Protocol annotation scanner (https://github.com/hierynomus/scannit) with hardcoded class name:
Scannit scannit = new Scannit(Configuration.config()
.scan("com.xebialabs")
.with(new AbstractScanner[] { new TypeAnnotationScanner() }));
The command
Thread.currentThread().getContextClassLoader().getResources("com/xebialabs")
returns null.
Looks like EJB runs in a separate classloader which does not have access to all the jars.
The EJB is packed to EAR with following structure:
EAR
--META-INF
----sda-dd.xml
----SAP_MANIFEST.MF
----MANIFEST.MF
----application-j2ee-engine.xml
--ejb.jar
--extlibs.jars
The MANIFEST.MF file don`t contain any referenses to external libs in CLASS-PATH. The EAR project is deployed to Application server successfully.
The EJB.jar also contains META-INF/MANIFEST.MF with value "Class-Path: ." by default.
I`ve already tried playing around with CLASS-PATH in manifest files, but have no luck.
Could anyone help me, how to build project with all external libs to be loaded while EJB runs? What have I missed with resources and classloaders?
Where to put files in a Tomcat Servlet application, such that they are relatively visible to the page??
More detail:
I am developing a servlet page while using an external library. That library depends massively on external loaded XML files (relative file paths). So I need to put these XML files in the running directory of the servlet.
Is there a way in Tomcat server, where files can be accessible relatively?
When a web application is deployed to Tomcat, the root of the web application ends up being $CATALINA_HOME/webapps/YOUR_WEB_APP/
As such, if using a servlet to access an XML file located on a path within the root of your web application, you can just use the following:
request.getServletContext().getResourceAsStream("PATH/TO/YOUR/XML_FILE.xml")
This will load the XML file as an InputStream. Of course, if you want access to the file itself, you can always use the getResource(String resource) method to obtain a URL, from which a File object can be obtained like so (alternative methods included):
File f;
try {
f = new File(url.toURI());
} catch(URISyntaxException e) {
f = new File(url.getPath());
}
EDIT: To make them relatively visible to a web browser, simply keep them out of the ./WEB-INF and ./META-INF directories.
If this library you are talking about is going to search for the file on the classpath (like Hibernate or Log4J would do), you will have to put your XML file in WEB-INF. However, I suggest you do not do this manually. You can put the file in a source directory of you application, which will make sure the file gets deployed on the right spot.
This is an old question. I'm working on Tomcat 9. I've been quite successful with taking the Tomcat installation directory as the base. (CATALINA_HOME) The relative path to a file in ROOT for example is then, "webapps/ROOT/someDir/fileName"
The place to complain about repeated answers is to deal with repeated questions.
Is it possible for a web application to access its own deployed folder. I am using JSF 1.2 framework and i need to access some of the files which i have it in the deployed directory.
Does JSF has any in built method to give us the deployed folder and the files in it?
Use ExternalContext.getResourcePaths("/"). In a servlet container, this will delegate to ServletContext.getResoucePaths(String). As the documentation notes:
For example, for a web application
containing:
/welcome.html
/catalog/index.html
/catalog/products.html
/catalog/offers/books.html
/catalog/offers/music.html
/customer/login.jsp
/WEB-INF/web.xml
/WEB-INF/classes/com.acme.OrderServlet.class
/WEB-INF/lib/catalog.jar!/META-INF/resources/catalog/moreOffers/books.html
getResourcePaths("/") would return
{"/welcome.html", "/catalog/",
"/customer/", "/WEB-INF/"}, and
getResourcePaths("/catalog/") would
return {"/catalog/index.html",
"/catalog/products.html",
"/catalog/offers/",
"/catalog/moreOffers/"}.
For portable code, do not assume you can access resources via the file system:
This method (getResource(String)) allows the servlet container to make a resource available to servlets from any source. Resources can be located on a local or remote file system, in a database, or in a .war file.
You can get access to resources in the classpath, but the servlet API does not guarantee their physical representation. In other words, if you deploy a WAR file, the container may explode the WAR file or keep it as is, or do something completely different depending on its needs.
In this particular context it mean that you introduce a subtle container dependency by assuming that a web application is deployed to a folder, which you should be very careful about.
If all you need, however, is to get some items you have in the classpath you should have a look at this question: Getting the inputstream from a classpath resource (XML file)
FacesContext.getCurrentInstance().getExternalContext().getResource("/").toString();
you will get the path to your WEB-INF/classes dir traverse using parent(); method from File class to get the location