Apache clustering and load balancing with tomcat 8 in ubuntu - apache

I want to do clustering and load balancing for my applications running in tomcat. I am using ubuntu, apache version 2.4.18 and two tomcat 8.5 instances. I tried with mod_jk for this but it is not working for me.
following is my configuration in apache and tomcat
in jk.conf
<IfModule jk_module>
JkWorkersFile /etc/apache2/conf/workers.properties
JkLogFile /etc/apache2/log/mod_jk.log
JkLogLevel info
JkShmFile /etc/apache2/log/jk-runtime-status
JkWatchdogInterval 60
JkMount /clusterjsp/* loadbalancer
JkMount /jk-status status
<Location /jk-status>
JkMount jk-status
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Location>
<Location /jk-manager>
JkMount jk-manager
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Location>
</IfModule>
in workers.properies
worker.list=loadbalancer,status
worker.server1.port=8009
worker.server1.host=127.0.0.1
worker.server1.type=ajp13
worker.server1.connection_pool_size=200
worker.server1.connection_pool_timeout=600
worker.server1.socket_keepalive=1
worker.server2.port=7009
worker.server2.host=127.0.0.1
worker.server2.type=ajp13
worker.server2.connection_pool_size=200
worker.server2.connection_pool_timeout=600
worker.server2.socket_keepalive=1
worker.server1.lbfactor=1
worker.server2.lbfactor=1
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=server1,server2
worker.status.type=status
and in both tomcat server.xml
<Engine name="Catalina" defaultHost="localhost" jvmRoute="server1"> <!-- server2 for another instance -->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8">
<Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/>
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="50"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps" 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>
i did not make any changes in apache2.conf or i don't have httpd.conf in apache home directory. i have deployed same application i both tomcat servers and it is working when using http://localhost:8080/clusterjsp and http://localhost:7070/clusterjsp but When i type http://localhost/clusterjsp in my browser it gives me 404 error but http://localhost shows apache default page.
Can you please let me know what i am missing or what is wrong in my configuration.

Probably it is due to the fact that you are redirecting all incoming requests matching /clusterjsp/* to load balancer, but you don't take care of the requests which don't have anything after the context path. You could try just adding this line to your jk.conf:
JkMount /clusterjsp loadbalancer
There are other aproaches too, but probably this is the easyest one to test.

Related

SSL between apache and JBoss

We have the next configuration:
one apache server with version 2.2.14.
two application servers with JBoss Application Server version 7.1.1 in domain mode.
We configure a virtual hosts and mod_cluster discover application servers without problem, but when I add the configuration for ssl then mod_cluster cannot discover application servers.
The file httpd-vhosts.conf is:
Listen <ip>:10001
MemManagerFile /var/cache/httpd
<VirtualHost <ip>:10001>
ErrorLog "/usr/IBMAHS/logs/error_ssl_log"
TransferLog "/usr/IBMAHS/logs/access_ssl_log"
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile "/usr/IBMAHS/pki/file.com.crt"
SSLCertificateKeyFile "/usr/IBMAHS/pki/file.com.key"
<Directory />
Order deny,allow
Allow from all
</Directory>
KeepAliveTimeout 60
MaxKeepAliveRequests 0
ManagerBalancerName other-server-group_d
ServerAdvertise On
AdvertiseFrequency 5
#EnableMCPMReceive
#This directive allows you to view mod_cluster status at URL http://<ip>:10001/mod_cluster-manager
<Location /mod_cluster-manager>
SetHandler mod_cluster-manager
Order deny,allow
Allow from all
</Location>
</VirtualHost>
Can anyone help me?
I assume you would like to have this setup up and running:
clients <-- SSL --> balancer <-- SSL --> AS7 workers
and that you are aware of severe performance drawback of its
balancer <-- SSL --> AS7 workers
part. The following setup works, yet one must be aware of the fact that connection between client and AS7 worker is not transparent and that the balancer acts more or less like a man-in-the-middle. If clients trust the balancer, balancer trusts the workers and workers trust the balancer, it's all good.
Here you go bro:
Apache HTTP Server with mod_cluster
MemManagerFile "/opt/httpd/cache/mod_cluster"
ServerName 10.16.94.122:2181
<IfModule manager_module>
Listen 10.16.94.122:8847
# As soon as it works, remove/change this...
LogLevel debug
<VirtualHost 10.16.94.122:8847>
ServerName 10.16.94.122:8847
<Directory />
Order deny,allow
Deny from all
# Obviously, testing purposes...
Allow from all
</Directory>
KeepAliveTimeout 60
MaxKeepAliveRequests 0
ServerAdvertise on
AdvertiseFrequency 5
ManagerBalancerName qacluster
AdvertiseGroup 224.0.5.188:23364
EnableMCPMReceive
SSLEngine on
SSLCipherSuite AES128-SHA:ALL:!ADH:!LOW:!MD5:!SSLV2:!NULL
SSLCertificateFile /opt/ssl/proper/server.crt
SSLCertificateKeyFile /opt/ssl/proper/server.key
SSLCACertificateFile /opt/ssl/proper/myca.crt
#SSLVerifyClient require
#SSLProxyVerify require
SSLProxyEngine On
SSLVerifyDepth 10
<Location /mcm>
SetHandler mod_cluster-manager
Order deny,allow
Deny from all
# Obviously, testing purposes...
Allow from all
</Location>
</VirtualHost>
</IfModule>
AS7 worker, standalone-ha.xml, could be applied to a proper in domain as well:
AS7 worker
+++
</extensions>
<system-properties>
<property name="javax.net.ssl.trustStore" value="/opt/ssl/proper/client-cert-key.jks"/>
<property name="javax.net.ssl.trustStorePassword" value="you-shall-never-know"/>
</system-properties>
<management>
+++
</management>
<profile>
+++
<subsystem xmlns="urn:jboss:domain:modcluster:1.1">
<mod-cluster-config advertise-socket="modcluster" connector="https">
<dynamic-load-provider>
<load-metric type="busyness"/>
</dynamic-load-provider>
<ssl key-alias="javaclient" password="you-shall-never-know" certificate-key-file="/opt/ssl/proper/client-cert-key.jks"
cipher-suite="AES128-SHA:ALL:!ADH:!LOW:!MD5:!SSLV2:!NULL" ca-certificate-file="/opt/ssl/proper/ca-cert.jks"/>
</mod-cluster-config>
</subsystem>
+++
<subsystem xmlns="urn:jboss:domain:web:1.5" native="false">
<connector name="https" protocol="HTTP/1.1" scheme="https" socket-binding="https" secure="true" enabled="true">
<ssl name="https" key-alias="javaclient" password="you-shall-never-know" certificate-key-file="/opt/ssl/proper/client-cert-key.jks"
cipher-suite="AES128-SHA:ALL:!ADH:!LOW:!MD5:!SSLV2:!NULL" protocol="TLS" verify-client="false"
certificate-file="/opt/ssl/proper/client-cert-key.jks" ca-certificate-file="/opt/ssl/proper/ca-cert.jks"/>
</connector>
<virtual-server name="default-host" enable-welcome-root="true">
<alias name="localhost"/>
<alias name="example.com"/>
</virtual-server>
</subsystem>
+++
</profile>
<interfaces>
+++
</interfaces>
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
+++
<socket-binding name="https" port="8443"/>
+++
<socket-binding name="modcluster" port="0" multicast-address="224.0.5.188" multicast-port="23364"/>
+++
Let us know if it works for you. In future, you might actually target the JBoss mod_cluster forums directly :-)
Have you a sample configuration for standalone (not clustered) ?

How to mask a tomcat app behind an apache subdomain?

I have two separate servers: an Apache public server and an internal Tomcat one. I would like our users to be able to use our Tomcat apps without exposing the details of our implementation (actual port, server name, context) through the public Apache server like this:
http://credits.publicdomain.com/servlet
instead of
http://tomcat.internaldomain.com:8082/CreditsApp/servlet
How can I configure my Apache server to mask requests to our Tomcat apps this way? Is using Apache modules such as mod_rewrite or mod_proxy the most straightforward approach?
I have tried this configuration for a VirtualHost in Apache, which works for the first servlet. However it seems to disable Tomcat to keep the session from the first servlet to any other servlet you go afterwards:
ServerName credits.publicdomain.com
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://tomcat.internaldomain.com:8082/CreditsApp/
ProxyPassReverse / http://tomcat.internaldomain.com:8082/CreditsApp/
Am I missing some additional configuration in my Tomcat server in order to work without the context between servlets?
The best and most efficient way to do this is using mod_jk: http://tomcat.apache.org/connectors-doc/
I've used this in several projects and found it to be extremely easy to use, effective, flexible, and performant. It's also the de facto official solution to stacking Tomcat behind Apache.
mod_jk is what you need to bridge Tomcat to Apache, so you can focus on your app
and Apache, as the front-end, can deal with https and authentication and such. It will forward certain URLs to 'workers' in Tomcat. So you need to tell Apache to load the mod_jk, you need to configure worker.properties, Apache would need to know which worker does what, and you need to define a Service in Tomcat.
These directives in httpd.conf configure mod_jk:
JKWorkersFile conf/workers.properties
JKLogFile /var/log/tomcat/mod_jk.log
JKLogLevel info
The JKWorkersFile in /etc/httpd/conf/workers.properties basically defines sockets
workers.tomcat_home=/var/tomcat4
workers.java_home=/usr/java/jdk
ps=/
worker.list=worker1,worker2
worker.worker1.port=8009
worker.worker1.host=localhost
worker.worker1.type=ajp13
worker.worker2.port=8010
worker.worker2.host=localhost
worker.worker2.type=ajp13
This snippet for httpd.conf would delegate everything (i.e. /* ) to worker1:
<VirtualHost 192.0.34.72>
ServerAdmin webmaster# example.com
DocumentRoot /www/www.example.com/webapps/ROOT
ServerName www.example.com
ErrorLog logs/public_errors
LogLevel debug
CustomLog logs/public_access combined
JkMount /* worker1
<Directory "/www/www. example.com/webapps/ROOT">
Options Indexes FollowSymLinks Indexes
AllowOverride None
Order allow,deny
Allow from all
</Directory>
<Location "/WEB-INF/">
AllowOverride None
deny from all
</Location>
<Location "/META-INF/">
AllowOverride None
deny from all
</Location>
</VirtualHost>
And Tomcat would have this service:
<service name="public">
<connector classname="org.apache.coyote.tomcat4.CoyoteConnector" port="8009" minprocessors="5" maxprocessors="75" enablelookups="true" redirectport="8443" acceptcount="10" debug="0" connectiontimeout="0" useurivalidationhack="false" protocolhandlerclassname="org.apache.jk.server.JkCoyoteHandler" />
<engine name="Standalone" defaulthost="localhost" debug="0">
<logger classname="org.apache.catalina.logger.FileLogger" prefix="catalina_log." suffix=".txt" timestamp="true" /> <realm classname="org.apache.catalina.realm.UserDatabaseRealm" debug="0" resourcename="UserDatabase" /> 
<host name="localhost" debug="0" appbase="/www/www.example.com/webapps" unpackwars="true" autodeploy="true">
<logger classname="org.apache.catalina.logger.FileLogger" directory="logs" prefix="localhost_log." suffix=".txt" timestamp="true" />
</host>
</engine>
</service>
The above examples are from my notes, check update documentation at:
http://tomcat.apache.org/connectors-doc/generic_howto/workers.html
http://tomcat.apache.org/connectors-doc/webserver_howto/apache.html

Spring security 3 Concurrent session control not working in tomcat clustered environment

Spring security's concurrent session control is not working properly in tomcat 7 clustered environment but works fine in non-clustered environment.Sessions are also replicated in tomcat.
Configuration for clustering:
<Cluster channelSendOptions="6" className="org.apache.catalina.ha.tcp.SimpleTcpCluster">
<Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/>
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership address="228.0.0.9" className="org.apache.catalina.tribes.membership.McastService" dropTime="3000" frequency="500" port="45564"/>
<Receiver address="auto" autoBind="100" className="org.apache.catalina.tribes.transport.nio.NioReceiver" maxThreads="6" port="5008" selectorTimeout="5000"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" deployDir="/tmp/war-deploy/" tempDir="/tmp/war-temp/" watchDir="/tmp/war-listen/" watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
Configuration for apache load balancing:
ProxyPass / balancer://domain.foo.net/ lbmethod=byrequests stickysession=JSESSIONID|jsessionid nofailover=Off maxattempts=15
ProxyPreserveHost On
<Proxy balancer://domain.abcprocure.net>
BalancerMember http://127.0.0.1:8888 max=250 min=45 keepalive=On route=tc02
BalancerMember http://127.0.0.1:8080 max=250 min=45 keepalive=On route=tc01
</Proxy>
Further assistance would be appreciated.
The default SessonRegistry is an in-memory implementation so you will have a different one in each JVM which will be unaware of the others.
You need to implement the SessionRegistry interface in a way that shares data between VMs. This could use a SQL database, memcached, redis or whatever is most appropriate for your situation.
Once you've written your class, the reference manual shows how to configure concurrency control with an explicit SessionRegistry bean.

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

How to deploy multiple Grails apps on one Tomcat + Apache?

I've read the several questions on StackOverflow and googled several hours but I can't find a complete and clear answer to my problem of deploying multiple Grails apps on one tomcat 5.5 (with Apache). Maybe someone can push me in the right direction or we can summarize a solution here.
The question Deploying multiple grails applications with Apache/Tomcat + Virtual Hosts looked promising but did not work. Maybe I need to do additional changes in Tomcat or Apache?
THE SITUATION:
In the webapps directory of Tomcat I have two war-files app1.war and app2.war which are getting unpacked by Tomcat and which I can access via domain1.com/app1 or domain1.com/app2 (I removed a previously used ROOT.war and the associated webapps/ROOT/ directory)
In the server.xml of Tomcat I have the following hosts:
<!-- Logger shared by all Contexts related to this virtual host. -->
<Logger className="org.apache.catalina.logger.FileLogger"
directory="logs" prefix="localhost_" suffix=".log"
timestamp="true"/>
<!-- Allow symlinks for the tomcat-docs webapp. This is required in
the Debian packages to make the Servlet/JSP API docs work. -->
<Context path="/tomcat-docs" docBase="tomcat-docs" debug="0">
<Resources className="org.apache.naming.resources.FileDirContext"
allowLinking="true" />
</Context>
</Host>
<Host name="domain1.com" appBase="webapps/app1" unpackWARs="true" autoDeploy="true"></Host>
<Host name="domain2.com" appBase="webapps/app2" unpackWARs="true" autoDeploy="true"></Host>
In Apache I have the following virtual hosts:
ServerName app1.com
JkMount /* default
DocumentRoot /var/lib/tomcat5.5/webapps/app1
<directory /var/lib/tomcat5.5/webapps/app1>
Options -Indexes
</directory>
LogLevel warn
ErrorLog /var/www/app1/logs/error.log
CustomLog /var/www/app1/logs/access.log common
The Problem:
I cannot directly access the two applications via domain1.com and domain2.com - what am I doing wrong?
Many thanks in advance,
Joerg.
I struggled with this a while back and managed to get something that works ok. It doesn't use mod_jk though, I opted for mod_proxy. I also had a slightly different set up in Tomcat (mine is version 6 btw), where I added multiple connectors as well as the Host declarations you have.
Try the following -
In tomcat server.xml:
<!-- I opted for a shared thread pool so both apps share same resources - optional -->
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="250" minSpareThreads="40"/>
<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8444"
executor="tomcatThreadPool"
proxyName="www.domain1.com"
proxyPort="80"/>
<Connector port="8082" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8445"
executor="tomcatThreadPool"
proxyName="www.domain2.com"
proxyPort="80"/>
<Host name="www.domain1.com" appBase="vhosts/domain1" unpackWARs="true"
autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Alias>domain1.com</Alias>
</Host>
<Host name="www.domain2.com" appBase="vhosts/domain2" unpackWARs="true"
autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Alias>domain2.com</Alias>
</Host>
In Apache:
<VirtualHost *:80>
ServerName www.domain1.com
ServerAlias www.domain1.com
ProxyRequests Off
ErrorLog /var/log/apache2/error-domain1.log
<Directory proxy:http://www.domain1.com:80>
Order Allow,Deny
Allow from all
</Directory>
<Proxy www.domain1.com:80>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://localhost:8081/
ProxyPassReverse / http://localhost:8081/
ProxyPreserveHost On
</VirtualHost>
<VirtualHost *:80>
ServerName www.domain2.com
ServerAlias www.domain2.com
ProxyRequests Off
ErrorLog /var/log/apache2/error-domain2.log
<Directory proxy:http://www.domain2.com:80>
Order Allow,Deny
Allow from all
</Directory>
<Proxy www.domain2.com:80>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://localhost:8082/
ProxyPassReverse / http://localhost:8082/
ProxyPreserveHost On
</VirtualHost>
Make sure mod_proxy is enable for your Apache server. It was a while ago when I got this working, so I'm sure if everything is needed in that config - once I get it working I tend to forget stuff :)
Hope that helps,
Chris.
we have two Grails Web App running in production under the same tomcat
That was easy to do with tomcat 6
The difference I see with your server.xml is the name of the apps
here what we have :
<Host name="www.domain1.com" appBase="[tomcat_root_dir]/www.domain1.com/webapps" unpackWARs="true"
autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
</Host>
<Host name="www.domain2.com" appBase="[tomcat_root_dir]/www.domain2/webapps" unpackWARs="true"
autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
</Host>
Then we have two directories domain1.com and domain2.com in tomcat root dir
In each directory, we have a webapps dir which holds only a ROOT.war file for each app
Hope that helps
Cheers
Grooveek