Friday, November 22, 2013

Tapestry 5 https, Tomcat and load balancer plain HTTP proxy

We usually place Tapestry 5 apps running on Tomcat behind an Apache HTTPD with mod_jk / mod_proxy_ajp or mod_proxy_http.

Request protocols are plain HTTP or secure HTTPS from users to the Apache and same thing from Apache to Tomcat. Tapestry 5 auto-detects requests protocol and creates suitable URLs for further calling back actions for the application.

Below are 2 examples:
1. Browsers --http--> Apache --http--> Tomcat --Tapestry 5--http --> Apache --http--> Browsers ...
2. Browsers --https--> Apache --https--> Tomcat --Tapestry 5--https --> Apache --https--> Browsers ...

When we deploy an app required to access via https to load balancers connect to Tomcat in plain http proxy as:
3. Browsers --https--> Load balancers --http--> Tomcat--Tapestry 5 --http--> Load balancers --https --> Browsers ...

Then we get into the browser error “Blocked loading mixed active content” when loading an https page and mix some other http requests in background via AJAX within a page.

The reason is the Tomcat always got http requests from load balancers, so Tapestry 5 builds base URLs in http protocol.

Tapestry 5 allows us to override how these default URLs are created by the BaseURLSource service.

But that's not a good way to go with because we have to decide what protocol should be returned for each deploy environment in code...

Google around and found these posts:

Teaching Tapestry to use network path references
[T5]: BUG: Proxy Situation: Tapestry 5.3.3 Not Respecting isSecure for Form Action URL
Problem pushing application to production

The last one is very helpful when Kalle said about Tomcat connector configuration with proxyPort..

Study more about it and found a solution:

Tomcat http connector should be reconfigured as:
<Connector port="8080" proxyPort="443" secure="true" scheme="https"
protocol="HTTP/1.1" connectionTimeout="20000" URIEncoding="UTF-8" redirectPort="8443"/>

And http proxy in Apache/load balancer:
ProxyPreserveHost On
ProxyPass /T5app http://tomcat:8080/T5app
ProxyPassReverse /T5app http://tomcat:8080/T5app

So the Apache/load balancer handles https come from browsers, but makes http proxy to Tomcat and the Tomcat returns secure https/443 when Tapestry needs to build base URLs.

App web.xml

Saturday, November 16, 2013

Ehcache RMI Replicated Caching in cloud environments

The RMI Ehcache provides 2 ways for peer discovery: Automatic Peer Discovery and Manual Peer Discovery.

If the application is deployed in an environment where multicast is not allowed or not available like Amazon AWS or FireHost clouds, then we must use Manual Peer Discovery.

Follow the guide, configure Manual Peer Discovery as:

Configuration for server1

Configuration for server2


Configuring the CacheManagerPeerListener as:
properties="hostName=server1, port=40001,

properties="hostName=server2, port=40001,

So we need to open the firewall for incoming TCP port 40001 on both peers.

But then each peer server can't send message to other with the connection timed out error:

RMIAsynchronousCacheReplicator Unable to send message to remote peer.  Message was: Connection refused to host: server2; nested exception is: Connection timed out
java.rmi.ConnectException: Connection refused to host: server2; nested exception is: Connection timed out
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(
    at sun.rmi.transport.tcp.TCPChannel.createConnection(
    at sun.rmi.transport.tcp.TCPChannel.newConnection(
    at sun.rmi.server.UnicastRef.invoke(
    at net.sf.ehcache.distribution.RMICachePeer_Stub.send(Unknown Source)
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator.writeReplicationQueue(
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator.replicationThreadMain(
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator.access$000(
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator$
Caused by: Connection timed out

Review the guide/google around... to find out the problem, but couldn't know why? Then tried to change the firewall to allow all ports and it worked!

So absolutely there was another port that was used by the Ehcache but blocked by the firewall.

Google around and found the answer here
"by default does use portmap and therefore random, non-root ports."

So we need to add remoteObjectPort to the cacheManagerPeerListenerFactory as:
properties="hostName=server1, port=40001, remoteObjectPort=40002,

properties="hostName=server2, port=40001, remoteObjectPort=40002,

And close all ports on the firewall except TCP 40001, 40002 between those peers.

Problem is resolved.

Friday, November 1, 2013

Multiple Tomcat instances on single server and session issue

When setting up 2 instances for Tomcat 6 on the same server, we got the issue of both are sharing sessions when both have same application context name. So if we logged into one instance, the session of the other will be expired.

The reason is cookie is stored by domain and cookie name, but not specified by server port. So both instances use the same JSESSIONID cookie name.

To fix it, we need to change the org.apache.catalina.SESSION_COOKIE_NAME parameter on java command.

We could do that easily with Tomcat bin/ by adding that parameter to JAVA_OPTS: