Tomcat subdomain association - apache

I have a Spring application accessible as www.mydomain.com on Amazon AWS. Now I want another Spring application under the same Amazon instance (and hence using the same tomcat) to be accessible under mysubdomain.mydomain.com. My tomcat is fronted with Apache.
App corresponding to www.mydomain.com is located at:
/env/tomcat/apache-tomcat-7.0.26/webapps/ROOT
For the app to be accessible at mysubdomain.mydomain.com, I have created another folder at:
/env/tomcat/apache-tomcat-7.0.26/mysubdomainapps/ROOT
Below are the contents of server.xml and httpd.conf
server.xml
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Note: A "Server" is not itself a "Container", so you may not
define subcomponents such as "Valves" at this level.
Documentation at /docs/config/server.html
-->
<Server port="8005" shutdown="SHUTDOWN">
<!-- Security listener. Documentation at /docs/config/listeners.html
<Listener className="org.apache.catalina.security.SecurityListener" />
-->
<!--APR library loader. Documentation at /docs/apr.html -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
<Listener className="org.apache.catalina.core.JasperListener" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources
Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<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>
<!-- A "Service" is a collection of one or more "Connectors" that share
a single "Container" Note: A "Service" is not itself a "Container",
so you may not define subcomponents such as "Valves" at this level.
Documentation at /docs/config/service.html
-->
<Service name="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools-->
<!--
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>
-->
<!-- A "Connector" represents an endpoint by which requests are received
and responses are returned. Documentation at :
Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
Java AJP Connector: /docs/config/ajp.html
APR (HTTP/AJP) Connector: /docs/apr.html
Define a non-SSL HTTP/1.1 Connector on port 8080
-->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!-- A "Connector" using the shared thread pool-->
<!--
<Connector executor="tomcatThreadPool"
port="80" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
-->
<!-- Define a SSL HTTP/1.1 Connector on port 8443
This connector uses the JSSE configuration, when using APR, the
connector should be using the OpenSSL style configuration
described in the APR documentation -->
<!--
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
-->
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<!-- An Engine represents the entry point (within Catalina) that processes
every request. The Engine implementation for Tomcat stand alone
analyzes the HTTP headers included with the request, and passes them
on to the appropriate Host (virtual host).
Documentation at /docs/config/engine.html -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
-->
<Engine name="Catalina" defaultHost="localhost">
<!--For clustering, please take a look at documentation at:
/docs/cluster-howto.html (simple how to)
/docs/config/cluster.html (reference documentation) -->
<!--
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
-->
<!-- Use the LockOutRealm to prevent attempts to guess user passwords
via a brute-force attack -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the Realm. -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
**<Host name="mysubdomain.mydomain.com" appBase="mysubdomainapps" unpackWARs="true" autoDeploy="true"></Host>**
</Engine>
</Service>
</Server>
httpd.conf
<VirtualHost *:80>
ServerName localhost
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
</VirtualHost>
<VirtualHost *:80>
ServerName mysubdomain.mydomain.com
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
</VirtualHost>
It's been hours I'm trying to sort it out, but couldn't succeed.
I'd really appreciate your help.
Thanks,
James

It worked! For DNS, I had created a CNAME earlier. I tried with A-record, and it worked great!

Related

Issues with configuration of Bitbucket Server with HTTPS reverse proxy using Tomcat

I'm trying to install some Atlassian products (Bitbucket Server, Jira, Confluence etc.) on my VPS with using HTTPS. Every product should be available on their own subdomain e.g. https://bitbucket.mydomain.de or https://jira.mydomain.de I tried many things but now I'm very confused. It always redirect me to the Tomcat-GUI instead of my installed Bitbucket Server application. Maybe managing the ports is too confusing for me.
Three configuration files are involved - Tomcats server.xml, Apaches mydomain.conf file and Bitbuckets bitbucket.properties configuration.
I've tried to use an own Bitbucket Connector in Tomcat, while using an reverse Proxy in Apache. Here are some of my files.
Apaches mydomain.conf
<VirtualHost *:443>
ServerName bitbucket.mydomain.de
ServerAlias bitbucket.mydomain.de
ProxyRequests Off
<Proxy *>
Require all granted
</Proxy>
ProxyPass / http://bitbucket.mydomain.de:7990/
ProxyPassReverse / http://bitbucket.mydomain.de:7990/
SSLEngine on
SSLCertificateFile /etc/ssl/certs/mydomain_ssl_certificate.cer
SSLCertificateKeyFile /etc/ssl/private/mydomainprivate_key.key
SSLCertificateChainFile /etc/ssl/certs/mydomain_ssl_certificate_intermediate.cer
</VirtualHost>
Bitbuckets bitbucket.properties
server.port=7990
server.secure=true
server.scheme=https
server.proxy-port=443
server.proxy-name=bitbucket.mydomain.de
And Tomcats server.xml
<Server port="8005" shutdown="SHUTDOWN">
<...>
<Service name="Catalina">
<!-- Default Connector -->
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"/>
<!-- Bitbucket Connector -->
<Connector port="7990" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="443" compression="on" compressableMimeType="text/html,text/xml,text/plain,text/css,application/json,application/javascript,application/x-javascript"
secure="true" scheme="https" proxyName="bitbucket.mydomain.de" proxyPort="443" />
<!-- SSL Connector -->
<Connector port="8443" maxHttpHeaderSize="8192" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false"
disableUploadTimeout="true" acceptCount="100" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keyAlias="tomcat"
SSLEnabled="true" keystoreFile="keystore/mydomain-keystore.jks" keypass="mypass" keystoreType="JKS"/>
</Service>
</Server>
Actually, it shows me on bitbucket.mydomain.de every single time the Tomcat GUI instead of Bitbucket.. and I can't explain why. What am I missing? I think the whole server.xml is misconfigured...
Thanks a lot for every help!
You can use something a little bit lighter than Apache like haproxy. Haproxy is available as a standard Linux package. Haproxy will terminate your SSL connection. It will act as a reverse proxy for the various Atlassian applications. See the following link for information on how to set it up:
https://confluence.atlassian.com/bitbucketserver/securing-bitbucket-server-behind-haproxy-using-ssl-779303273.html
You won't have to change your Tomcat server.xml

Redirect HTTP to HTTPS:PORT in Tomcat

I have a running tomcat application that already have the following redirection rule from HTTP to HTTPs:
<Connector executor="tomcatThreadPool"
port="80"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="443" />
Is it possible to add an exception/rule, that a specific HTTPrequest (http://www.example.com), will be redirected to another specific address , with a port specified (say https://www.example.com:8443/test), without changing/removing the above Connector ?
You can do it to every app deployed to tomcat by adding this to the end of tomcat_dir/conf/web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>Entire Application</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<!-- auth-constraint goes here if you requre authentication -->
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
So you don't have to change it on the web.xml of your webapp.
That should work, assuming you already have https working in another port (usually 443). If you don't, make sure your tomcat_dir/conf/server.xml looks like this:
<!-- Default tomcat connector, changed the redirectPort from 8443 to 443 -->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="443" />
<!-- To make https work on port 443 -->
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"/>
<SSLHostConfig>
<Certificate certificateKeyFile="/your/own/privkey.pem"
certificateFile="/eyour/own/cert.pem"
certificateChainFile="/your/own/chain.pem"
type="RSA" />
</SSLHostConfig>
</Connector>
The connector configuration you shown does not redirect a specific URL in the way you suppose.
That configuration acts if you have configured a CONFIDENTIAL transport guarantee for a web application inside that servlet container.
I mean, if you have deployed any application on that connector, where its web.xml descriptor has a security-constraint as follows:
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
...
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
Then, Tomcat will redirect any matching url-pattern to the configured port in order to use HTTPS as guarantor of confidentiality in transport.
So, if you want to redirect a specific URL, you have to complement connector's configuration with specific application configuration.
Edit
As you suggest in your comment, it could be another step to get this configuration working. Once you have configured http connector as shown, and then configured app as I told you, you only to ensure that your Tomcat server has an HTTPS connector configured, other way redirection won't work.
To configure this HTTPS connector, you can use a configuration as following:
<Connector connectionTimeout="20000"
acceptCount="100" scheme="https" secure="true"
port="443" clientAuth="false" sslProtocol="TLS"
keystoreFile="PATH_TO_KEY_STORE"
keystorePass="KEY_STORE_PASS"
keyAlias="KEY_STORE_ALIAS"/>
This is a sample configuration where I didn't put some attributes that can be important for you as threads attrs, executors, and so on.
The most important thing is the KeyStore configuration that you need to serve HTTPS connections. Here you have the official documentation to prepare a java KeyStore for Tomcat to serve HTTPS.
I have a running tomcat application that already have the following redirection rule from HTTP to HTTPs:
As malaguna answered, that Connector configuration is not a redirection rule. It is just a setting that is used when performing redirection triggered by <transport-guarantee>CONFIDENTIAL</transport-guarantee>.
There is no way to overwrite that setting on per-application basis.
If you need better control over such redirection, you need to implement your own Filter that will implement a redirection (if (!request.isSecure()) { response.sendRedirect(...);}), or configure a 3rd party one.
// Technically, in current Tomcat 8 code the redirection triggered by transport-guarantee is performed by org.apache.catalina.realm.RealmBase.hasUserDataPermission(...) method.
If you use tomcat with httpd, you can use RewriteEngine.
With port specified is like the followings in the http.conf:
NameVirtualHost *:8443 #your specified port
<VirtualHost *:8443>
ServerName www.example.com
Redirect permanent / https://secure.example.com/
</VirtualHost>
See: RewriteHTTPToHTTPS and Redirect Request to SSL
Putting transport-guarantee CONFIDENTIAL in conf/web.xml is good, but it does not cover the manager app and the host-manager app (Tomcat 8.5.38).
My solution is to put a valve in conf/context.xml that redirects all http requests to https.
https://bitbucket.org/bunkenburg/https-valve/src/master/
It's too late to answer, still I'm sharing my experience over the same, do the following changes in
Apache Software Foundation\Tomcat 8.5\conf\web.xml
Take a restart.
Pre-Req: configure https port and disable http port(optional[I did it])
<Connector connectionTimeout="20000" port="8081" protocol="HTTP/1.1" redirectPort="443"/>
<Connector port="443"
SSLEnabled="true"
acceptCount="100"
disableUploadTimeout="true"
enableLookups="false"
maxHttpHeaderSize="8192"
maxThreads="550"
minSpareThreads="25"
scheme="https"
secure="true"
compression="on"
protocol="org.apache.coyote.http11.Http11NioProtocol"
sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"/>
<SSLHostConfig protocols="TLSv1.2"
certificateVerification="none"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA">
<Certificate type="RSA"
certificateKeystoreFile="/ssl/self-signed/your-keystore.jks"
certificateKeystorePassword="123456"
certificateKeyAlias="your-alias" />
</SSLHostConfig>
   </Connector>

Did I do anything wrong when config Server.xml to point another domain into a folder that is not a ROOT folder in webapps folder?

Ok, I have a main domain: mainDM.com (which is the domain of the app named mainDM) bought from Godaddy. I also bought a Godaddy Win2000 VPS with IP adress xxx.xx.xx.xx.
In Godaddy I pointed that domain into xxx.xx.xx.xx.
In Tomcat server, in webapps folder, there is a ROOT folder & I put all html files of mainDM application into the ROOT folder. Everything work fines. That is when I opened mainDM.com I can see my app running OK.
Now, I developed another app called otherDM & I also bought a domain otherDM.com in Godaddy & I also pointed it into xxx.xx.xx.xx. Now when opening otherDM.com, I do not see the otherDM app but mainDM app. So I want to config server.xml so that when I open otherDM.com, it will show otherDM web app. Note: There is an otherDM folder that containing all html files of otherDM app in webapps folder.
Here is what I did at server.xml, but nothing happened.
<?xml version='1.0' encoding='utf-8'?>
<!-- Note: A "Server" is not itself a "Container", so you may not
define subcomponents such as "Valves" at this level.
Documentation at /docs/config/server.html
-->
<Server port="8005" shutdown="SHUTDOWN">
<!-- Security listener. Documentation at /docs/config/listeners.html
<Listener className="org.apache.catalina.security.SecurityListener" />
-->
<!--APR library loader. Documentation at /docs/apr.html -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
<Listener className="org.apache.catalina.core.JasperListener" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources
Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<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>
<!-- A "Service" is a collection of one or more "Connectors" that share
a single "Container" Note: A "Service" is not itself a "Container",
so you may not define subcomponents such as "Valves" at this level.
Documentation at /docs/config/service.html
-->
<Service name="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools-->
<!--
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>
-->
<!-- A "Connector" represents an endpoint by which requests are received
and responses are returned. Documentation at :
Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
Java AJP Connector: /docs/config/ajp.html
APR (HTTP/AJP) Connector: /docs/apr.html
Define a non-SSL HTTP/1.1 Connector on port 8080
-->
<Connector port="80" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!-- A "Connector" using the shared thread pool-->
<!--
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
-->
<!-- Define a SSL HTTP/1.1 Connector on port 8443
This connector uses the BIO implementation that requires the JSSE
style configuration. When using the APR/native implementation, the
OpenSSL style configuration is required as described in the APR/native
documentation -->
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
-->
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<!-- An Engine represents the entry point (within Catalina) that processes
every request. The Engine implementation for Tomcat stand alone
analyzes the HTTP headers included with the request, and passes them
on to the appropriate Host (virtual host).
Documentation at /docs/config/engine.html -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
-->
<Engine name="Catalina" defaultHost="localhost">
<!--For clustering, please take a look at documentation at:
/docs/cluster-howto.html (simple how to)
/docs/config/cluster.html (reference documentation) -->
<!--
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
-->
<!-- Use the LockOutRealm to prevent attempts to guess user passwords
via a brute-force attack -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the Realm. -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
<Host name="otherDM.com" appbase="otherDM" autoDeploy="true" unpackWARs="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="otherDM_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
I did restart my Tomcat server but nothing happened, each time I open the otherDM.com then it shows the mainDM app. However, if I open otherDM.com/otherDM or open mainDM.com/otherDM then I can see otherDM app.
Did I do anything wrong? How to fix?
The "appbase" attribute of a "host" tag points, if relative, as in your case, to a directory below CATALINA_HOME. So just create two folders like this:
[CATALINA_HOME]/mainDomain
[CATALINA_HOME]/otherDomain
and create two ROOT folder in them. Copy you apps into the ROOT directories.
Then set the appbase to:
<Host name="localhost" appBase="mainDomain" ...
<Host name="mainDomain.com" appBase="mainDomain" ...
<Host name="otherDomain.com" appBase="otherDomain" ...
I fixed,
First, I do what Stefan said, created
[CATALINA_HOME]/otherDM
And put all html files into the ROOT of mainDM and otherDM accordingly.
Then, add a Host into server.xml
<Host name="localhost" appBase="mainDM" ...
<Host name="otherDM.com" appBase="otherDM" ...
Finally I need to add ROOT.xml into C:\tomcat7\conf\Catalina\otherDM.com\ROOT.xml
<Context
docBase="C:/tomcat7/otherDM/ROOT"
path=""
reloadable="true"
/>
AN now it work perfectly and I can add many domains as i can

Connecting Apache and Tomcat using mod_proxy_ajp works but JDBC then fails

I have a working Apache 2.2.16 on Debian Squeeze that serves some PHP applications from /var/www/ using different domains (e.g. phpApp1.com, phpApp2.com).
I also have a working Tomcat 7.x that lives in /opt/tomcat/ and servers a JSF+JPA application that lives in /opt/tomcat/webapps/MyApp/.
So MyApp can be accessed through e.g. myapp.com:8080/MyApp/home.html or phpApp1.com:8080/MyApp/home.html (because of the port). Since I wanted this to be myapp.com/home.html instead, I connected Apache and Tomcat using mod_proxy_ajp using the following config files:
An Apache virtual host in /etc/apache2/sites-available/MyApp
<Virtualhost *:80>
ServerName myapp.com
ServerAlias *.myapp.com
ProxyPass / ajp://localhost:8009/
ProxyPassReverse / ajp://localhost:8009/
</Virtualhost>
And a Tomcat virtual host in /opt/tomcat/conf/server.xml
<Host name="myapp.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="" reloadable="true" debug="0" docBase="MyApp" />
<Alias>www.myapp.com</Alias>
</Host>
This works to the point that I cann access http://myapp.com/home.html and get a correct html page including css, images and js. So the AJP connector in tomcat should work.
BUT the app fails to establish a JDBC connection that otherwise works fine. It does not matter whether i use myapp.com or myapp.com:8080, it fails either way. However, it works if I access my app throug http://phpapp1.com:8080/MyApp/home.html. It only fails when I use the proxy-domain "myapp.com".
Has anyone experienced similar problems when using AJP and JDBC? How can I solve this? I had the same problem when using mod_jk, which makes use of AJP, too. Thanks in advance.
Update 1
#Mark Rotteveel: What do you mean by "connecting directly"? I mean the JDBC connection is working if I use one of the domains that are not listed as virtual hosts in tomcats server.xml.
Here is the connection error:
ERROR: HHH000231: Schema export unsuccessful
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1452)
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1371)
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
at org.hibernate.service.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:141)
at org.hibernate.tool.hbm2ddl.SuppliedConnectionProviderConnectionHelper.prepare(SuppliedConnectionProviderConnectionHelper.java:51)
at org.hibernate.tool.hbm2ddl.DatabaseExporter.<init>(DatabaseExporter.java:52)
at org.hibernate.tool.hbm2ddl.SchemaExport.execute(SchemaExport.java:367)
at org.hibernate.tool.hbm2ddl.SchemaExport.create(SchemaExport.java:304)
at org.hibernate.tool.hbm2ddl.SchemaExport.create(SchemaExport.java:293)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:492)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1744)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:94)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:905)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:890)
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:57)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:63)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47)
at com.myapp.util.database.Database.<init>(Database.java:70)
at com.myapp.util.database.Database.<clinit>(Database.java:38)
at com.myapp.controller.file.UploadBacking.ajaxUpload(UploadBacking.java:89)
at com.myapp.controller.file.UploadBacking$Proxy$_$$_WeldClientProxy.ajaxUpload(UploadBacking$Proxy$_$$_WeldClientProxy.java)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.el.parser.AstValue.invoke(AstValue.java:264)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:39)
at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
at org.apache.myfaces.view.facelets.el.ContextAwareTagMethodExpression.invoke(ContextAwareTagMethodExpression.java:96)
at org.apache.myfaces.view.facelets.tag.jsf.core.AjaxHandler$AjaxBehaviorListenerImpl.processAjaxBehavior(AjaxHandler.java:495)
at javax.faces.event.AjaxBehaviorEvent.processListener(AjaxBehaviorEvent.java:57)
at javax.faces.component.behavior.BehaviorBase.broadcast(BehaviorBase.java:74)
at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:405)
at javax.faces.component.UICommand.broadcast(UICommand.java:103)
at javax.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:1028)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:286)
at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1375)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:752)
at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:38)
at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:170)
at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:197)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:183)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:200)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.NullPointerException
at sun.jdbc.odbc.JdbcOdbcDriver.getProtocol(JdbcOdbcDriver.java:507)
at sun.jdbc.odbc.JdbcOdbcDriver.knownURL(JdbcOdbcDriver.java:476)
at sun.jdbc.odbc.JdbcOdbcDriver.acceptsURL(JdbcOdbcDriver.java:307)
at java.sql.DriverManager.getDriver(DriverManager.java:253)
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1437)
... 60 more
From Database.java:
private Database() {
entityManagerFactory = Persistence.createEntityManagerFactory("myapp_persistence_unit");
}
MyApp/META-INF/context.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Context>
<Context>
<Resource
name="jdbc/db_myapp"
auth="Container"
type="javax.sql.DataSource"
username="user_myapp"
password="##########"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/db_myapp?autoReconnect=true"
validationQuery="select 1"
maxActive="15"
maxIdle="3" />
<Valve
className="org.apache.catalina.valves.AccessLogValve"
directory="logs/myapp"
prefix="myapp_access_"
suffix=".log"
pattern="%h %l %u %t "%r" %s %b"
resolveHosts="false" />
</Context>
From WEB-INF/web.xml
<resource-ref>
<description>MySQL database</description>
<res-ref-name>jdbc/db_myapp</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
And finally WEB-INF/classes/META-INF/persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="myapp_persistence_unit">
<properties>
<property name="hibernate.connection.datasource" value="java:comp/env/jdbc/db_myapp" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<property name="hibernate.current_session_context_class" value="thread" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
</persistence-unit>
</persistence>
I finally got it to work. If you create a virtual host in tomcat, you have to put an exact copy of your applications /META-INF/context.xml into /tomcat/conf/Catalina/domain.com/ and name it context.xml.default. Well, I don't know if this is always the case, but for my setting it was. So these are my current config files that do the job:
/etc/apache2/sites-enabled/domain.com
<Virtualhost *:80>
ServerName domain.com
ServerAlias *.domain.com
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / ajp://my.server.ip:8009/
</Virtualhost>
/tomcat/conf/server.xml
<Host name="domain.com">
<Context path="" docBase="MyApp" />
<Alias>www.domain.com</Alias>
</Host>
I tried this after reading this thread on coderanch.com from 2006 (the authors solution is in the last post). I did not change the web.xml or context.xml since this was not a misconfiguration of the <Resource> element. Anyway, thanks for your attempts to help :)
Make sure you have your mysql-connector-j.x.y.z.jar file in exactly one place: Tomcat's lib directory. Make sure you don't have a stray copy in any of your webapps' WEB-INF/lib directories.
Two unrelated tips:
Don't use autoReconnect
Use /* ping */ SELECT 1 as your validation query: recent versions of Connector/J will use a lightweight "ping" instead of actually issuing a query in order to test a connection's validity

Tomcat / Apache / Grails Config

Hoping someone can help / advise as i'm not very familiar with Apache / Tomcat .. I already have Apache in front of Tomcat with grails app deployed. I have IIs setup (by someone else) which redirects www.xyz.com/myApp to an Apache instance which runs a grails app. In my apache conf I have a proxy ..
ProxyPass /myApp http://localhost:8080/myApp
ProxyPassReverse /myApp http://localhost:8080/myApp
and I have a connector defined in my tomcat server.xml
<Connector port="8080" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
proxyName="www.xyz.com"
proxyPort="443" />
This works without problem
I now want to add another app so in IIS I had setup for me www.xyz.com/myOtherApp
with
ProxyPass /myOtherApp http://localhost:8081/anotherApp
ProxyPassReverse /myOtherApp http://localhost:8081/anotherApp
in my Apache conf I added another connector
<Connector port="8081" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
proxyName="www.xyz.com"
proxyPort="443" />
When i go to www.xyz.com/myOtherApp i get the url rendered (correctly i think) as https://www.xyz.com/anotherApp but with a 404 error saying "Object not Found" ..
Can anyone help me with the config ? Is it possible to have 2 connectors on different ports
with the same proxyName ? As i say i'm not familiar with Apache/Tomcat and i'd really like to get this done asap ..
Thanks
Hi #Stefan, The apps do live on the same server and domain so i eliminated one of the connector definitions . I'm now left with
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JasperListener" />
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<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" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
proxyName="www.xyz.com"
proxyPort="443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
</Host>
</Engine>
</Service>
</Server>
Also I switched on the logging (JULI) but it didn't seem to report anything . The apache error log just gives me a 404 .. I left it as HTTP rather than AJP as i'd have to setup HTTPS and i'm not sure how easy that is. So i'm left with the same problem in that one app works, the other doesn't .. Is it possible to run multiple grails apps over http as opposed to using ajp and virtual hosts ? Forgive me if i'm being stupid - i haven't had much exposure to webapps and i seem to have come to a grinding halt at what i thought should have been relatively easy - deployment !
If you want to use Apache in front of Tomcat, it's better to use mod_proxy_ajp instead of mod_proxy_http. For setting this up, see https://confluence.sakaiproject.org/display/~steve.swinsburg/Fronting+Tomcat+with+Apache+via+mod_proxy_ajp.
Be sore to add
ProxyRequests Off
<Proxy *>
Order deny,allow
Deny from all
Allow from localhost
</Proxy>
to your config to prevent abuse of the proxy.
If /myApp and /myOtherApp reside in the same tomcat engine, you only need a single connector for both apps. Aside from this, I can see no obvious error in your setup. Maybe you could post your tomcat's server.xml. During working on the config, using LogLevel Debug might be a good idea.
This isn't a direct answer to your question, but I was configuring Tomcat behind Apache before and I had problem with it.
I now use Amazons Elastic beanstalk...where you can deploy your grails app war file directly. It works a beautifully, especially with in built auto scaling and health monitoring!
Less configuration == Ease of life.