How to request contents from an external directory in Tomcat? - java

To be precise I need to get pictures from an external directory say: C:/MWDB.
I found this link: How to config Tomcat to serve images from an external folder outside webapps? which I wanna follow up with the part where you need to add a directory in your server.xml context tag.
So Basically Based on the way it says I came with that it should be like:
<Context docBase="C:/MWDB" path="/images" reloadable="true" source="org.eclipse.jst.jee.server:Duck"/> (request: www.example.com/images/image.png) with this way while restaring the server it pops me an error saying
The server at localhost has encountered a problem
Which then I did this: <Context docBase="C:/MWDB" path="/images"/> And This I can't even access my index.html file
FULL server.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Server port="20011" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
<Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
<GlobalNamingResources>
<Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
</GlobalNamingResources>
<Service name="Catalina">
<Connector connectionTimeout="20000" port="20012" protocol="HTTP/1.1" redirectPort="8443"/>
<Connector port="20013" protocol="AJP/1.3" redirectPort="8443"/>
<Engine defaultHost="localhost" name="Catalina">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log" suffix=".txt"/>
<Context docBase="C:/MWDB" path="/images" reloadable="true" source="org.eclipse.jst.jee.server:Duck"/></Host>
</Engine>
</Service>
</Server>
I'm using Java 8, Apache Tomcat v9.0

Okay I figured out my problem.
Basically What I didn't know is that you could have multiple <context> at the same time.
So When I had something like:
<Context docBase="C:/MWDB" path="/images"/>
I could Server from only MWDB directory and not my internal Project and that is why I couldn't access my index.html file. So For to server from both directory Simply you can do:
<Context docBase="C:/MWDB" path="/images" reloadable="true" source="org.eclipse.jst.jee.server:Duck"/>
<Context docBase="C:/MWDB" path="/images"/>
Works Perfectly so far :)

Related

Error when looking up Context in Java Tomcat application when using multiple WARs [duplicate]

I would like to run two tomcat services on two ports (8080,8181) with different codeBases, but sharing the same database resource. When I do this, I get "javax.naming.NameNotFoundException: Name [comp/env/jdbc/mydb] is not bound in this Context. Unable to find [comp]." when it tries to initialize the second Service.
My Services look like this in the server.xml:
...
<GlobalNamingResources>
<Resource auth="Container" name="jdbc/mydb" url="jdbc:db2://myserver:50000/mydb" username="xxx" password="xxx" .... />
</GlobalNamingResources>
...
<Service name="Catalina8080">
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
....
<Host name="localhost" appBase="webapps8080" unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" .... />
</Host>
</Engine>
</Service>
<Service name="Catalina8181">
<Connector port="8181" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8444" />
<Engine name="Catalina" defaultHost="localhost">
....
<Host name="localhost" appBase="webapps8181" unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" .... />
</Host>
</Engine>
</Service>
My server level context file looks like :
<Context>
...
<ResourceLink name="jdbc/mydb" global="jdbc/mydb" type="javax.sql.DataSource" />
</Context>
I've tried adding and removing the Resource links at the application level context file, but nothing seems to change the outcome. Any thoughts are greatly appreciated.
You should change the name of your <Engine> in the second service: there can be only one naming context for each combination of engine name, host name and context name.
In your case the combination (Catalina, localhost, your application name) probably appears twice, hence you should be able to find an entry like this:
SEVERE [main] naming.namingContextCreationFailed
in the logs and JNDI doesn't work in the second context.

Can I have multiple folders like webapps and specify what domains to access which ROOT.war file

I am using apache apache-tomcat-8.5.6 for deploying my web applications. I have a webapps folder and a ROOT.war file under webapps and all my domains by default access this ROOT.war file.
Now I am planning to add two more folders similar to webapps, let's say folder1 and folder2 and planning to deploy ROOT.war under both these folders.
Now I want a certain domain to access ROOT.war under folder1 and another to access folder2. All other domains by default should access ROOT.war under webapps.
I believe that this is possible and might need some changes under the server.xml file. I am new to server configurations. Is there any good documentations or su
This is absolutely possible.
The key of this solution is that the Engine-Tag attribute "defaultHost" names the application-Host which is used by default and the Host-Tag attribute "name" contains the domain name which uses this application if it matches.
Example server.xml:
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource
auth="Container"
description="Database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
name="UserDatabase" pathname="conf/tomcat-users.xml"
type="org.apache.catalina.UserDatabase" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" useBodyEncodingForURI="true" />
<Engine defaultHost="defaultHost" name="Catalina">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase" />
<Host
name="defaultHost"
appBase="webapps-leave-empty">
<Valve
className="org.apache.catalina.valves.AccessLogValve"
directory="${catalina.base}/logs/access/"
rotatable="true"
buffered="true"
prefix=""
suffix="-access.log"
fileDateFormat="yyyyMMdd"
pattern='%a %t %v "%r" %s %b "%{Referer}i" "%{User-Agent}i" %I' />
<Context docBase="<PathToDefaultApplication>" path="" />
</Host>
<Host
name="<SpecialDomain1>"
appBase="webapps-leave-empty">
<Valve
className="org.apache.catalina.valves.AccessLogValve"
directory="${catalina.base}/logs/access/"
rotatable="true"
buffered="true"
prefix=""
suffix="-access.log"
fileDateFormat="yyyyMMdd"
pattern='%a %t %v "%r" %s %b "%{Referer}i" "%{User-Agent}i" %I' />
<Context docBase="<PathToApplication1>" path="" />
</Host>
<Host
name="<SpecialDomain2>"
appBase="webapps-leave-empty">
<Valve
className="org.apache.catalina.valves.AccessLogValve"
directory="${catalina.base}/logs/access/"
rotatable="true"
buffered="true"
prefix=""
suffix="-access.log"
fileDateFormat="yyyyMMdd"
pattern='%a %t %v "%r" %s %b "%{Referer}i" "%{User-Agent}i" %I' />
<Context docBase="<PathToApplication2>" path="" />
</Host>
</Engine>
</Service>
</Server>

Duplication server name in URL

I have a trouble with configure of Apache and Tomcat. My purpose is to get ability to adress to tui.org/servlet, when tui.org is my virtual host configured on local machine and /servlet/ is url-pattern which is defined at web.xml. But instead the servelet I get 404 Not Found by Tomcat but I can to adress to my server by tui.org/tui.org/servlet - it works. Structure of files on my server is the following:
Root: /var/www/tui.org
-------->/WEB-INF/classes/a
-------->/WEB-INF/classes/a/MainServlet.class
-------->/WEB-INF/web.xml
-------->/index.html
How can I achieve this behaviour?
web.xml:
<servlet-mapping>
<servlet-name>mainServlet</servlet-name>
<url-pattern>/servlet</url-pattern>
</servlet-mapping>
My server.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="/var/www/"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
Configuration of tui.org (tui.org.conf at /etc/apache2/sites-available:
<VirtualHost *:80>
ServerName tui.org
DocumentRoot /var/www/tui.org
<Directory /var/www/tui.org>
AllowOverride All
Require all granted
</Directory>
JkMount /servlet* ajp13_worker
</VirtualHost>
I use Apache2, tomcat9 and Ubuntu 18.04.
Thank you in advance!
P.S. Sorry for my english.
There are several issues here:
You must not serve the web application directory with Apache - e.g. you're declaring DocumentRoot /var/www/tui.org for Apache and <Host appBase="/var/www/"> for Tomcat.
e.g but not limited to: The servlet spec specifically disallows to serve the directory WEB-INF to ever be served to a client, and you're explicitly bypassing this limitation.
An application deployed in a Host's appBase is always deployed under that name (unless specified differently in a context.xml file). The only other exception to that rule is if a directory is called ROOT - in that case, it's deployed without a name, thus omitting the tui.org that follows your server name.
but this is secondary to the issue of serving the whole webapp through Apache httpd. Fix that one first.
One way to fix your biggest problem is to omit the DocumentRoot directive in Apache and rather serve everything from Tomcat: JkMount * ajp13_worker.
For solving problem with adressing by tui.org/servlet I had to add <Context> directive to server.xml:
<Context path="" docBase="/var/www/tui.org/"/>
and change appBase from /var/www/ to /var/www/tui.org/.
And for fix problem with access to WEB-INF (thanks to #OlafKock) I had to add next to tui.org.conf:
<Directory /var/www/tui.org>
AllowOverride All
Deny from all
</Directory>

Edit application path when using AWS Elastic Beanstalk

With local tomcat my application url is: http://ip:port/myapp
but when deploying it to AWS Elastic Beanstalk the url becomes http://some_domain.com. I want the url to be http://some_domain.com/myapp.
How do I do that? I found something about adding some config file to .ebextensions but I wasn't sure what exactly I should do and whether it helps at all.
UPDATE:
I created an .ebextensions folder and put the the following files:
server.xml
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
<Listener className="org.apache.catalina.core.JasperListener"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
<GlobalNamingResources>
<Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
</GlobalNamingResources>
<Service name="Catalina">
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
<Engine defaultHost="localhost" name="Catalina">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log." suffix=".txt"/>
<Context docBase="EizeRest" path="/EizeRest" reloadable="true" source="org.eclipse.jst.jee.server:EizeRest"/>
</Host>
</Engine>
</Service>
</Server>
server-update.config
container_commands:
replace-config:
command: cp .ebextensions/server.xml /etc/tomcat7/server.xml
And when deploying I'm getting the following error:
"aws Unable to detect application deployment"
Here is a screenshot:
Another update:
I see in the events tab of the server the following error: cannot stat '.ebextensions/server.xml': No such file or directory
I believe you will need to take the following steps:
create a Tomcat server.xml file that sets path=myapp
copy this file to beanstalk during its deployment phase
Beanstalk documentation provides a relevant guide for that here:
http://aws.typepad.com/aws/2012/10/customize-elastic-beanstalk-using-configuration-files.html
Basically the guide says you need to copy the server.xml to beanstalk by creating the following file in your application root: .ebextenstions/tomcat.config:
container_commands:
replace-config:
command: cp .ebextensions/server.xml /etc/tomcat7/server.xml
don't forget to commit both the server.xml and the tomcat.config files in the .ebextensions folder.
You must place your ".ebextensions" folder at the same level as your WEB-INF folder. Doing that will remove the ".ebextensions/server.xml: No such file or directory" error.

javax.naming.NamingException, Tomcat7 and Struts2 can't access to DB resource via JNDI

I'm developing new web app with Struts2 framework, eclipse, and I've mapped the db structure with Hibernate. The problem is that when I execute my "list" action the framework returns me this error:
Struts Problem Report
Struts has detected an unhandled exception:
Messages:
This context must be accessed through a java: URL
Unable to lookup JNDI name [java:comp/env/jdbc/main]
File: org/apache/naming/SelectorContext.java
Line number: 776
The server.xml is:
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
<Listener className="org.apache.catalina.core.JasperListener"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
<GlobalNamingResources>
<Resource auth="Container" defaultAutoCommit="false" driverClassName="net.sourceforge.jtds.jdbc.Driver" maxActive="200" maxIdle="100" maxWait="20000" name="jdbc/main" password="########" type="javax.sql.DataSource" url="jdbc:jtds:sqlserver://10.4.1.85/SBAGRU_DEV" username="****"/>
</GlobalNamingResources>
<Service name="Catalina">
<Connector connectionTimeout="2000" executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
<Connector SSLEnabled="true" clientAuth="false" keystoreFile="C:\jpeople.bin" keystorePass="gesbanke" keystoreType="PKCS12" maxThreads="200" port="8443" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="SSL"/>
<!--<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/> -->
<Engine defaultHost="localhost" name="Catalina">
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">
<Context docBase="mag0" path="/mag0" reloadable="true" source="org.eclipse.jst.jee.server:mag0">
<ResourceLink global="jdbc/main" name="jdbc/main" type="javax.sql.DataSource" />
</Context>
</Host>
</Engine>
</Service>
</Server>
I've also hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
<Listener className="org.apache.catalina.core.JasperListener"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
<GlobalNamingResources>
<Resource auth="Container" defaultAutoCommit="false" driverClassName="net.sourceforge.jtds.jdbc.Driver" maxActive="200" maxIdle="100" maxWait="20000" name="jdbc/main" password="########" type="javax.sql.DataSource" url="jdbc:jtds:sqlserver://10.4.1.85/SBAGRU_DEV" username="****"/>
</GlobalNamingResources>
<Service name="Catalina">
<Connector connectionTimeout="2000" executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
<Connector SSLEnabled="true" clientAuth="false" keystoreFile="C:\jpeople.bin" keystorePass="******" keystoreType="PKCS12" maxThreads="200" port="8443" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="SSL"/>
<!--<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/> -->
<Engine defaultHost="localhost" name="Catalina">
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">
<Context docBase="mag0" path="/mag0" reloadable="true" source="org.eclipse.jst.jee.server:mag0">
<ResourceLink global="jdbc/main" name="jdbc/main" type="javax.sql.DataSource" />
</Context>
</Host>
</Engine>
</Service>
</Server>
Any suggestion where I can look? I'm really going crazy!
I found the solution, and the real problem. I edit the server.xml in Eclipse, and I didn't watch the real publish result. For strange reason eclipse remove the resource link in the real server.xml, but show me the link in eclipse view. So i gooogled all day long and I find that I must add in the context.xml file under WEB-INF directory this:
<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="">
<ResourceLink global="jdbc/main" name="jdbc/main" type="javax.sql.DataSource" />
</Context>
Have you got a link to the resource in your web.xml:
<resource-ref>
<description>JTDS Datasource</description>
<res-ref-name>jdbc/main</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
for more info, check the Tomcat Docs: http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html
Generally a JDBC datasource is also configured as <Resource> as follows
<Resource name="jdbc/main" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="******" password="######" driverClassName="net.sourceforge.jtds.jdbc.Driver"
url="jdbc:jtds:sqlserver://10.4.1.85/SBAGRU_DEV"/>
You can try this inside tag. Just replace <ResourceLink> by above <Resource> element.
What you have done appears correct as <ResourceLink> is used to link the resources defined in <GlobalNamingResources> not sure why it's not working.
Please, take a look at this link
Hibernate + Tomcat 7
I have faced on the same problem: after the Tomcat update, this bug has disappeared.

Categories

Resources