Setup
I use Apache Tomcat 7 on an Arch linux distribution, and my webapps directory is located at /usr/share/tomcat7/webapps
. In this directory one should create a directory, and put META-INF and WEB-INF directories in it with xml configuration files. Then this directory will be the main path of the webapp. Thus for example:
If /usr/share/tomcat7/webapps/foo/bar.html
contains:
<!DOCTYPE html>
<html>
<body>
Hello world!
</body>
</html>
Then http://localhost:8080/foo
will show:
Hello world!
However, the goal is to have an external dynamic project (distributed by Netbeans in this case) as a webapp. So in that case I would like to locate my webapp here: /home/user/NetbeansProjects/foo/build/web/
(which contains bar.html
).
I've come up with three possible approaches but none are working and I think I'm missing something.
Approach 1 (symlink)
I was thinking, let's put a symlink (symbolic link) in the webapps directory using this command:
$ ln -s /home/user/NetbeansProjects/foo/build/web /usr/share/tomcat7/webapps/foo
This seems like the most elegant approach, but Tomcat is not able to read the directory. Why not?
Approach 2 (mount --bind)
I read that you could also redirect one directory to another using mount --bind
. So I tried to do this:
sudo mount --bind /usr/share/tomcat7/webapps/foo /home/user/NetbeansProjects/foo/build/web
Actually, this is the only solution that does work. Unfortunately, if I build the project again the mount will disappear. I have already tried to remount the directory after distributing the project using <exec/>
in Ant, but this makes Linux crash for some weird reason. So this is not an option either. Also remounting after every clean-build seems not a clean approach. Mounting is also not really used for this kind of stuff, so I imagine the solution will not involve mounting.
Approach 3 (server.xml)
The last thing I want to do is to go againsts the recommendations of the Apache folks (see here). Which says:
It is NOT recommended to place elements directly in the server.xml file.
So what do I do, I take the default server.xml and add this Context-tag to the Host-tag:
<Context docBase="/home/user/NetbeansProjects/foo/build/web/" path="/foo"></Context>
However, if I restart the Tomcat service it fails to start. In the logfiles I read:
SEVERE: Error starting static Resources
java.lang.IllegalArgumentException: Document base /home/user/NetbeansProjects/foo/build/web does not exist or is not a readable directory
So, obviously this must be some kind of permission problem. Since I double checked for spelling errors the path must be correct. But I am not able to solve this, what I have done to grant tomcat7 (group: tomcat7) permission is:
chown -R tomcat7:tomcat7 /home/user/NetbeansProjects/foo/build/web
chmod -R 755 /home/user/NetbeansProjects/foo/build/web
But after restarting Tomcat, the same error occurs and Tomcat fails to start.
Which approach above is the most sensible, and what am I doing wrong that's preventing it from working?
The exact reason of why Tomcat cannot read the directories as in approach 1 and 3 are still unknown to me. However, it seems impossible for Tomcat to use any directory located under
/home/user/...
as a webapp, even if this means using symlinks to link to this location and setting correct permissions on the directories!Although probably this is some kind of built-in protection. It is still strange because this behaviour is not listed in the Apache Tomcat documentation (correct me if I'm wrong).
The solution is therefore to use any other directory than
/home/user/...
, e.g./usr/share/tomcat7/projects
should work. But then again, it is best to set my Netbeans distribution output to the webapps directory directly as mentioned by another person (@user208992).So in order to fix this problem, here is a list of instructions necessary to make Tomcat work with Netbeans using an external build/dist directory:
Configure Netbeans to distribute the
build
anddist
directories to a directory outside of/home/user/NetbeansProjects/project
.Edit the following file:
/home/user/NetbeansProjects/project/nbproject/project.properties
, and change the lines:to
Note that you can use any directory (other than
/home/...
) instead of/srv/tomcat/project
Add a Context with a proper docBase to the Tomcat host.
One way to do this is to edit the
server.xml
configuration file probably located in/etc/tomcat7/server.xml
. Add a Context in theserver.xml
file:Make sure to place this within the
<Host>
-tag. Also you can add attributes to this tag when needed (reloadable, antiJARLocking etc). Or you could also place in xml file inCATALINA_HOME/engine(e.g. Catalina)/hostname(e.g. localhost)/project.xml
, one of these approaches will be okay.I choose to point the docBase to
.../build/web/
but you could also set this to.../dist/
if you want Tomcat to use the WAR-file.Make sure tomcat is in the same
users
-group as you are. To do this, e.g.:Note: Any common group you have with tomcat will suffice. This way Netbeans and Tomcat can both access the same directory.
Fix ownership and permissions of the external project directory.
This assumes that you
user
are member of the groupusers
, andtomcat7
is the name of tomcats user. You can check this in
cat /etc/passwd`.Note: Later on you can reduce the
777
-permissions, but to make sure to let Tomcat have permissions you can start with the most accessible permissions.Do clean/build in Netbeans, and restart tomcat service. This will apply the changes from the previous steps.
I hope this will be helpful to somebody dealing with a similar situation; Tomcat and permissions can be really hard to debug imho.
What @Schrute said in a comment (not an answer): Use option #1 (
ln -s
) and just allow linking in the Tomcat context.xml file. For Tomcat 7:Tomcat 8:
DO NOT DO THIS ON WINDOWS (or any other case-insensitive filesystem), as it will disable case sensitivity checks, allowing JSP source code disclosure, among other security problems. http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html
Why don't you just let your netbeans build to your desired directory?
It might be worth trying
setenforce 0
to disable selinux and retesting your above methods if selinux is enabled. If it works, re-enable selinux and start tracing down the permissions issues.There are all kinds of security concerns here... (If you wanted to do something like this on Cent/Oracle/REHL... most sysadmins will tell you that you'll have to disable selinux or spend several hours chasing the audit log)
Long story short, there is nothing
elegant
about instantly publishing a build of software anywhere. The amount of problems that can potentially arise are things of nightmares (especially with java and tomcat lurking in the background).You might do well to manually rsync from your development instance to a test instance. (IE Under Tomcat). If you want it to happen automatically.. You COULD add it to the build script.
Ps. I don't have time to look for supporting documentation... so: In my opinion it is neither best practice nor 'elegant' to combine the build and deploy stages of development (in almost all cases).
I do agree with lVlint67 about separating Build and Deploy, but I also often work with php/html/javascript in a dev URL where the separation just seems to get in the way. I use the symlink method, but the catch is that the permissions must be set to allow the web server to read the destination of the symlink.
I use:
For this to work, you have to be a member of the www-data group, and remember to keep your project files readable by group, and any files your app needs to write to will need to be writable by group.
This is all without SELinux, so your mileage may vary depending on your server config.