Java Servlet absolute paths outside webfolder [ Windows & Linux ] - java

Disclaimer : At the moment, due to lack of a Linux dev/test server, I am currently unable to test this myself. Hence me asking the question here. I will have a Linux box eventually but am currently confined to using Windows.
I am designing a webapp that will run in Tomcat 7 on Windows & Linux.
Supposing on both systems the WAR is deployed in the following locations (respectively)
/opt/Tomcat/webapps/MyApp
C:/opt/Tomcat/webapps/MyApp
The Webapp has a Servlet which needs to process files from the OS file system in the following locations
/work/logs/<logfiles>
C:/work/logs/<logfiles>
On Windows I can specify C:/work/logs and the Servlet knows to pick up this absolute path and it works fine. I suspect because the C: at the start. I know this because I have tested this.
My real question is...
On Linux, in the absence of a drive letter, if I ask it to look in /work/logs will it try to look at a relative path :
/opt/Tomcat/webapps/MyApp/work/logs
or will it look in the file system (/work/logs) as I'd like it to?
I'm asking this now because it will ultimately affect the overall design.

Leading slash in Linux means "absolute path", so you can be sure that if you use path like /work/logs/<something> it will understand it as an absolute path.
BTW if you use the same path in Windows it will work and use current disk, i.e. if tomcat's working directory is on C: it will use C: drive, however if tomcat is running on D: this drive will be used.

I can recommend using CATALINA_HOME environment variable to find a folder in which you place your config. For my projects I have the following structure:
$CATALINA_HOME/appconfig/ <-- config
$CATALINA_HOME/webapps/somewar.war <-- your webapps
Inside appconfig I will place a somewar.properties which functions as the configuration for that server. (I also place log4j.properties, and any special certificates / other things that are specific to the server instance you run on, but I try to keep it to a minimum)
As there will always be a CATALINA_HOME set for your project it is reusable.
inside the somewar.properties I would then list
work.path=/work/logs
Using /work/logs will work on both linux and windows as #AlexR mentions (in his much more to the point answer) but you can get into trouble as on linux you would need root access to be allowed to create the /work folder. It depends on who is managing the server and how strict they are.
I prefer the configuration solution so if you end up working on a machine that won't let you use a certain location, you can switch. Ofcourse you do need to be allowed to write inside CATALINA_HOME ;)

Related

Ensuring safe file access in both Windows and Linux

My team is doing Java Development on Windows, while our production server is running in Linux. We're using a lot of resource files in our projects, and because Windows and Linux use different file systems, it can happen that a file can be found in our development environment, but not in our production environment, e.g. "path/to/file/Filename.txt" can be found in Windows using the path "path/to/file/filename.txt", but the same path cannot find the desired file in Linux.
I'd like to make it so that anytime the file system is accessed in testing scope, it validates that the path will work in the Linux environment. I've figured out that a good test is to make sure that the absolute path is equal to the canonical path [file.getAbsolutePath().equals(file.getCanonicalPath())], but how can I make sure that this is checked everytime a file is accessed? I've thought about creating a new FileSystemProvider and overriding the default FileSystemProvider, but this is very complicated. Is there an easier way?

How do I change the Tomcat default working directory?

In my web application, when I do new File(".").getAbsolutePath(), the path returned is <tomcat_home>/bin. I want to change it to <tomcat_home>/webapps/<app_name>.
The default directory for HTML ./path works fine and is the path I want. But the Java path ./Path is different in the same project.
I have tried to add a parameter like workDir="Path" in the <Host> area of the server.xml file on my Tomcat server, but it doesn't work.
How do I change it?
The general question of how to change the working directory of a java process has been asked before. The simple answer is that the java language and the java virtual machine don't provide a way to change the working directory of the JVM process. You won't be able to change the working directory after tomcat has started.
Tomcat's startup scripts (bin/startup.sh and so on) don't set a working directory. The tomcat process will normally inherit whatever the current directory was for the startup script. See this question. To make tomcat start in a different working directory, you'll have to figure out what is launching tomcat, and change that process to change to the desired directory before it runs startup.sh.

Can't figure out cause for NoClassDefFoundError: aspose/pdf/Paragraph

I can't get any pages of my webapp to load (locally on Tomcat 7.0.2.6), due to this NoClassDefFound error. I'm at my wits end trying to figure out what the cause is, here is what I know:
My coworker has this project successfully running locally (on Tomcat) and on our development server (WebLogic).
I have done a fresh pulldown from svn so my code is exactly the same as his. I've verified that I have a shared library reference to Aspose (and that the required .jars are in there), and that weblogic.xml has an entry for it.
We saw this same error when initially deploying on WebLogic because the Aspose library was named incorrectly, but it ran fine locally on his Tomcat server.
I've tried cleaning and rebuilding the project to no effect.
As best as I can figure, it has to be either a Tomcat issue, or maybe an Eclipse setting.
Has anyone encountered a similar situation? Any ideas on what to try to resolve this?
First thing you need to do is determine if you are colliding with another class with the same name and package. The easiest way to do this is with the cygwin/linux console, save this shell script to a file say, findjar
find "$1" -name "*.jar" -exec sh -c 'jar -tf {}|grep -H --label {} '$2'' \;
put it in your path and navigate to the root of the server instance and run the script like this
findjar . yourclass
Note the period, dont forget it. this will return if you have multiple classes with the same name in your project.
once your sure the project is clean and there is only one copy of the class, i would try actually adding your shared libraries folder to the websphere server instances JVM arguments. to do that:
Go into the admin, click on servers
Open server types, click on websphere application servers
You should see your server listed there, click on it
On the right hand side, you will see a section “server infrastructure” and below that is a subsection “Java and process Management”
Open that section and click on “Process Definition”
On the process definition screen is another right hand column. Click on “Java Virtual Machine”
Yes, finally we are on the correct screen, there is an end in sight here, I promise
On the virtual machine page, there is a large text field labeled “Classpath” What you need to do is enter the full path to the shared libraries folder
its odd and makes no sense to have to do it, but i have had to do that in the past to allow my code to see the properties files in a shared resource.
It is possible that your colleague has java librarys installed within his Tomcat instance itself.
Take a look in the Tomcat directory for some lib folders (I cant remember the exact location and I think it changes based on the version) but something like ${CATALINE_HOME}/common/lib
Verify that he doesnt have differen JAR files in his tomcat installation as yours.
From this question: Does Tomcat load the same library file into memory twice if they are in two web apps?
They are apparently stored here:
Tomcat 6 $CATALINA_HOME/lib
Tomcat 5 $CATALINA_HOME/common/lib

Is there a way to get the application directory in Java?

This likely isn't possible, but I thought I would ask just to be sure. I have a batch file which starts my java app using relative paths. Ie. i have:
Application\start.bat
Application\lib*.jar
My application creates a configuration file in the Application directory. My batch script uses relative paths to point to the lib directory jars. This has worked really well for me because I can move the program wherever I want and it will just run. However now I would like to be able to call the same app from command line as well not just from a shortcut which has the working directory set to Application. The problem is that I want to be able to call my application from any directory on the command line and right now this doesn't work because the working directory will be different.
I know I can always add another parameter to my app for the working directory but then I still have to create a batch script with a hard coded path to my application. Is there any way around this in Java, for example to get the directory that my main java file is in on top of the working directory? Is there a launcher app perhaps?
I can't bundle my app as a jar because it creates configuration files which I want to be in the same directory as the application.
Consider just changing current dir in start.bat:
#cd /d %~dp0
java ...
This would change it to the folder where script is located.
pushd/popd commands can also be used to preserve current dir for calling script if needed.
Alternatively getClass().getProtectionDomain().getCodeSource().getLocation() can be used from java to get path to jar/classes.
There is also path-independent approach with config path system property:
java "-DconfigDir=%~dp0" ...
There is no portable solution that is going to work in all cases. Indeed, the notion of an application directory does not necessarily make sense; e.g. consider applets and applications launched using WebStart.
If the notion of an application or installation directory does make sense, then the simplest way to support it is to have the application's launcher / launch script pass it to the application Java code via an application specific -D property.

Where to put DLL file?

I am calling C++ method using DLL file in my Java project. Right now, I have hard coded the path.
The application will be deployed on many machines and it also run on multiple machine. Where should I put my DLL file so that I can load it and call it on any machine?
I've seen applications that put the DLL into the JAR file. At run-time, they extract the DLL from the JAR into a temporary directory and then access it there.
It's not the most efficient approach but the easiest from a deployment perspective.
You have to make sure your DLL is in the classpath.
One such way to do so is to put the path to the DLL in PATH environment variable.
Other option is to add it to the VM arguments in the variable LD_LIBRARY_PATH, like this:
java -Djava.library.path=/path/to/my/dll -cp /my/classpath/goes/here MainClass
If you are developing a complex application, that has to be stable you have to ensure that the DLL you need is put somewhere, where the OS is going to look for it, probably think of an installer script/program.
C:\WINDOWS\system32 (assuming C is the drive where windows is installed, probably you can get it from registry)
I used to use windows long time ago & not an expert, so I made a google search for you and find the link http://vlaurie.com/computers2/Articles/dll.htm
See the last topic in the link (the one starting with headline Using Regsvr32.exe to Register DLLs)

Categories