IIS7, Tomcat & Application Request Routing

Further Update: 27nd June 2011

Another update on this topic. If you were making the use of custom error pages in IIS7 and you implemented the below update, you may have noticed that the custom error commands are no longer being adhered to. To change this, you need to set up custom error pages at a site level by choosing your site, selecting “Error Pages”, then “Edit Feature Settings” from action menu and then “Custom error pages”.

Important Update: 22nd June 2011

On page 2 of this article (How To Configure IIS 7.0 and Tomcat with the IIS ARR Module), there is a key step that I failed to observe when I wrote the original post below.  The step in question is the enablement of the (reverse) proxy server after the ARR install.  By doing this, you are able to apply rewrite rules at the site level — something I wasn’t able to achieve originally, which meant that the routing rules within my server farm were somewhat overloaded.

With this setting enabled, I can leave a single delegation rewrite rule at the server farm level, telling IIS to delegate HTTP requests of a certain pattern but leave the rewrite rules that are there for beautification at the desired site level.  This is a much tidier and more scalable approach.

One gotcha that you need to be aware of is that the rewrites at the site level need to be absolute URLs.  Therefore, you could be tempted to place the host of a single tomcat instance that lay behind IIS direct in here and it would work fine but why not allow for a little future proofing and use localhost within all absolute URL site level rewrites, which isolates the rewrites used for masking ugly application URLs and delegates the job of request delegation to the server farm?  This approach would allow for the server farm config to be used to bring other tomcat instances online or taken offline for maintenance etc without having to change the site level configuration.  In other words, it keeps the various areas of the IIS7 interface focused on the job in hand allowing for easier administration.

Please keep this update in mind as you read the otherwise unchanged original post below.

Regards,

Dan

After many years of using the Tomcat Connector (http://tomcat.apache.org/connectors-doc/) when setting up Tomcat behind IIS, it is now time to say goodbye.

This is the conclusion that I’ve come to after having some particularly significant challenges using IIS7 on a 64bit Windows 2008 machine.

The traditional approach I’ve used in the past has been to utilise the Tomcat Connector, which is implemented as an ISAPI Filter, to delegate requests from IIS through to Tomcat.  This has worked great for me in the past and was the subject of a previous article (http://bit.ly/lp6zW) but the 64bit system threw in a couple of additional challenges that weren’t so easy to get around.

The problems faced led me to discover Application Request Routing (ARR), an official extension for IIS7, which allows you to define the delegation of requests to servers sitting behind the IIS instance.

What is particularly nice with this extension is the way in which it facilitates the former approach within the GUI, making it easier to understand what is being delegated.  The approach however, is similar to the ISAPI filter approach – delegating based on URL path patterns.

The following takes you through an overview of how to set this up:

1. Install ARR

You can obtain the appropriate install for the ARR IIS7 extension at http://www.iis.net/download/applicationrequestrouting

Once installed, the ‘Server Farms’ node indicates that it has installed correctly as indicated in the picture below.

ARR Install

The Server Farms node is seen if ARR is installed correctly

A number of  modules are added as part of this extension.  You can find the details of these from the same ARR link (http://www.iis.net/download/applicationrequestrouting)

2. Create Server Farm

Although the concept of a ‘farm’ of servers may be overkill for our needs of delegating HTTP requests through ISS7 to Tomcat, we shall never the less set up a farm containing one server – our Tomcat instance.

To do this:

  1. highlight the ‘Server Farms’ node in the left panel of the IIS7 Management Console .
  2. Choose ‘Create Server Farm’ from the right hand side action menu.
  3. You will be prompted for a name for the farm.  For my  needs in setting up the Open Text Delivery Server behind IIS7, I gave the farm the name ‘Tomcat – Delivery Server’.ARR Server Farm Name
  4. You will then be prompted to set up a server in the farm.  In our case, we are just going to select the localhost instance of Tomcat running on port 8080. To specify the port, open the ‘Advanced settings’.  Strangely, there appears to be no easy way to edit a servers port once set up so make sure you are correct, otherwise you will have to delete and add a new server.

    ARR Add Server

    Make sure you open the Advanced settings to edit the port number

3. Configure the Routing Rules

Now that we have informed IIS7 about the server that sits behind, we need to let it know how we wish to delegate HTTP requests to it.  To do this, we choose the newly created Server Farm in the left hand panel and select the Routing Rules feature.ARR Routing RulesWithin here, we have a few options.  I’ve chosen to keep the defaults of having both checkboxes checked and have no exclusions set as I am delegating this responsibility to the URL Rewrite Rules.

From here, you can add and modify the rewrite rules defining how requests are delegated using the ‘URL Rewite’ link in the right-hand action panel.

In my case, I chose to change the default rule that was set up for me to a regular expression as opposed to the wildcard default.  However, I only chose this due to personal preference.  The pattern I used for this rule is:

cps(.+)

and I ignore the case.

Finally, I have no Conditions or Server Variables to take note of in my scenario although they can easily be added here, so I conclude the rule by setting the action to ‘Route to Server Farm’ and chose my ‘Tomcat – Delivery Server’ farm with a path setting of

/{R:0}

This passes all URL path info through to Tomcat.  I also choose to stop processing of subsequent rules

4. Refine Rules for your Environment

Lastly, in my setup, I’ve added the following further rules to refine how my site is served through IIS7:

Delegate .htm and .html requests:

Pattern - ([^/]+.html?)
Action path - /cps/rde/xchg/<project>/default.xsl/{R:1}

Delegate .xml requests:

Pattern - ([^/]+.xml?)
Action path - /cps/rde/xchg/<project>/default.xsl/{R:1}

Delegate default home page

Pattern - ^/?$
Action path - /cps/rde/xchg/<project>/default.xsl/index.htm

Summary

Although this approach of using IIS7 in a reverse proxy capacity may not benefit from the efficiencies of the AJP protocol used by the Tomcat Connector, the impact in most sites will be negligible.  In exchange, you have a way of Tomcat and IIS7 working together in a way where the GUI of the IIS7 Management Console helps admins define and understand what is happening.  The ISAPI Filter approach is often not so visible because of the broad nature of what ISAPI modules can provide but also due to the configuration required outside of the IIS7 Management Console.

As always, if you have any questions, leave a comment.

64 thoughts on “IIS7, Tomcat & Application Request Routing

  1. Danny Baggs

    You’re welcome Morgan. We used exactly this approach on the http://www.solutionexchange.info site, which is turning out to be a bit of a reference for a few things.

    Let me know if there are other subjects you feel are worth covering and I’m sure between the great minds within the external community and some of the talented chaps internally of OT, we could better facilitate getting knowledge out to you guys.

    Reply
  2. rohit

    Hey Danny,

    Thanks for sharing this info, I am actually trying to integrate two applications, one written in Java and the other in .net. In doing so i want the IIS7 server to run in front of the java server and render the .net related pages, but when a request is made to any java based pased (URI will have /web/*), the request should be forwared to tomcat.

    Can you shed more light on the redirect rules in this case.

    Regards,
    Rohit

    Reply
  3. Danny Baggs

    Hey Rohit,

    If you see in step 3 of the post, I refer to a rewrite rule of cps(.+). Setting this up like this tells IIS7 that if you want to delegate requests coming via IIS that start with …/cps/ then these are delegated to the Tomcat server in my example.

    In your case, you can simply use web(.+) as you’ve alluded to this being your pattern to match.

    The key here is to select the Rewrite Rules option from the right-hand menu when you are within the Routing Rules area.

    Hope that helps,

    Dan

    Reply
  4. Pingback: Configuring TeamCity in IIS 7.5 « Charles Strahan's Blog

  5. Trevor

    Hi I am trying to do this and this seems straight forwarde enough but there are several issues that I am running into.
    1) my site is running on https://site.domain.cc and I am trying to connect to a tomcat that is running on 8080
    2) you did not mention what name you put in the servername
    3) did you remove the 443 mapping
    4) the last part of this is the the tomcat is only used to serve up birt reports the rest of the site is running in IIS.

    anythoughts

    I am trying to figure out why this is not working on my server.

    Reply
    1. Danny Baggs

      Hi Trevor,

      Sorry for the late reply.

      1) This should make no difference. Whether you expose your front controlling Web Server through HTTPS or not should not effect the communication between the Web Server and Tomcat running behind it. Not tried this myself but in theory you could map the httpsPort to 8080 or Tomcat’s HTTPS default – 8443 . Not sure how IIS uses those settings but if we’re both right with our assumptions then 8443 for Tomcat should work.
      2) In my case, Tomcat was running on the same machine as the Web Server, so I just used localhost for the server name.
      3) Didn’t need to use it in my case so left the default.
      4) I’m no expert with BIRT but would guess that this is irrelevant as we’re dealing only with HTTP and whatever is encapsulated within is insulated from this.

      My guess would be the HTTPS bit, so try mapping that to the Tomcat secure port.

      Hope that helps.

      Dan

      Reply
  6. Glenn

    Concerning – 4) the last part of this is the the tomcat is only used to serve up birt reports the rest of the site is running in IIS.

    In the viewer.properties (under WEB-INF) file (uncommnet out first) set the base_href key value to your server name:

    base_url=http://servername:8080

    Example uses port 8080, use whatever port your Tomcat is running on. I am assuming you are using the BIRT viewer.

    Reply
  7. Peter

    Great article Danny. I’m setting up the same thing. Have a windows server 2008 that uses ARR to redirect over to a different tomcat server. One weird behavior I see is that when I hit the tomcat manager through Firefox or IE 6, it prompts me for the tomcat admin login which I provide and get in. When I hit the url through IE7 or IE8, I got a different prompt asking me for the windows server login and not the tomcat manager login. Providing a correct account login doesn’t work and the page just breaks. any ideas on this odd behavior.

    Reply
    1. Danny Baggs

      Hi Peter,

      Thanks for your comment. I’m afraid I’m a little weak in the admin of web servers generally but the only thing I can think of is that there is something “special” going on in the Microsoft only world. At a guess, partially from experience, I would imagine that there is some kind of Integrated Windows Authentication setting turned on in your IIS instance, which initiates the NTLM or Kerberos protocols to exchange the credentials between browser and server. This will be only understood by browsers that understand the protocol out of the box – i.e. IE (no pun intended).

      I don’t know where you should look, but I would guess that an IIS setting will tell the server to use “Integrated Windows Authentication” or something similar when an area is “Unauthorized” a.k.a. how to react when an page request results in a HTTP 401 status. To further this guess, I would think that turning this setting off in IIS will simply delegate the task of how to deal with this to Tomcat through your delegation rules (rewrites etc).

      Drop a comment back here and let me know how you get on. I’d be interested to know if it helps and gets you closer as this is nothing more than an educated guess.

      Regards,

      Dan

      Reply
  8. Kirk

    Maybe you have an idea of what I am missing here . . .

    I have a similar set up as you (using Oracle OAS instead of Tomcat) but I am having a problem getting my url once it is rewritten to get picked up by ARR. It appears to be related to the rewrite as I can enter the url manually and it gets to my OAS just fine but if I let the rewrite take place (and the rewrite is happening, I can see the rewritten url in the log). I do have multiple sites whereas every example I have seen configuring ARR uses the default site and I’m thinking that the problem I am having is related to that (I need each site to be able use its own rewrite rules and routing scenarios).

    I have noticed that in the log that when I enter the complete url (which does get routed) the log entry has X-ARR-CACHE-HIT blah blah blah whereas when the URL is rewritten it does not have a reference to ARR and I get a 404.

    Also – when I create a rule at the site level, I don’t have a “Route to Server Farm” option in the action type as I do at the Server Farm/Routing Rules level (which may be by design or may indicate that the site is not aware of ARR).

    Any ideas?

    Thanks,

    Kirk

    Reply
    1. Danny Baggs

      Hi Kirk,

      Are you only using the rewrite functionality within the Server Farm configuration or are you also using the rewrite feature at a site or server instance level?

      From memory, the precedence of the rewrites in IIS doesn’t seem to be how you would imagine and that can cause confusion. For instance, although unrelated to the requests that need delegating to a secondary server (Tomcat in my case), the rewrites were not picked up correctly when I had them placed at a site level in tandem with my Server Farm rewrites.

      I addressed this by placing all rewrites, which may even be site specific, within the Server Farm rewrite rules and conditioning them with the host name. This does feel ugly and not right as you would think that these logically sit nicely at the site level.

      I’m not sure if this is what you were getting at so please feel free to comment back here if this hasn’t answered your question. Actually, please post back here if it has answered it too!

      Regards,

      Dan

      Reply
      1. Kirk

        Yeah – what you are describing is exactly what I am trying to do. Site based rewrites the same as I would do using isapi rewrite with an .htaccess file so that I could add the proper context name and path to the url which was then picked up by the tomcat connector and life was good. I’ll try moving my rewrites to the server farm level and start inspecting the host name and let you know.

        Thanks for the help,

        Kirk

        Reply
        1. Danny Baggs

          Hi Kirk,

          I had to play with this very scenario yesterday and I can add to this further.

          It would appear that rewrite rules added to even the Server Farm level, which should result in a rewrite (and not a re-routing/delegation) do not appear to work as expected. i.e. You add a rule that rewrites the URL into something that should match the delegation rule but this doesn’t work (even if you definitely uncheck the “Stop subsequent rules” checkbox). I found that this only worked if I effectively duplicated the delegation rule for this pattern as they didn’t seem to chain as expected.

          Hope this helps.

          Dan

          Reply
    1. Danny Baggs

      Hi Diane,

      Are you able to provide a little more information on your challenge? I don’t quite follow what you mean I’m afraid.

      Regards,

      Dan

      Reply
      1. Owen Medd

        I have a similar question. I want to use IWA (Integrated Windows Authentication) on a URL served by IIS 7.5. I can set this up with no problem and browsers that support IWA (IE) authenticate fine. What I really need is to somehow communicate that back to Tomcat. I believe the question is what is the best practice to send the REMOTE_USER (or LOGON_USER) server variable back to Tomcat?

        Is it as simple as adding the REMOTE_USER variable to the input rewrite rule to be forwarded with the request?

        I’ve poked around a bit and not found an answer to this question when using ARR, using the ISAPI connector seemed to be the only suggestion.

        Thanks,
        Owen

        Reply
  9. Brandon

    I like ARR and think it is pretty useful in a server farm scenario with ASP/ ASP.net. Super cool stuff.
    Not sure I like it as much on front-ending a tomcat instance though.
    Does not work well under load as both tomcat and arr really are not aware of each others load parameters. Leads to dropping of connections. Also found that working with certificates in these scenarios is challenging if possible at all.
    Unfortunately not much choice right now.
    Apache’s own ISAPI redirecter is pretty stale:
    http://wiki.apache.org/tomcat/Tomcat_and_IIS_Howto
    The new kid on the block is boncode connector. Seems to work but fresh project.
    http://tomcatiis.riaforge.org

    My 2:
    Brandon

    Reply
    1. Danny Baggs

      Thanks Brandon,

      Useful reference. I agree that the approach feels a little “hacky” due to the decoupled nature of the two servers but for me this is an acceptable trade-off as it allows a web admin to easily manage this connectivity through the IIS GUI and not through some workers.properties and urimappings.properties file. I appreciate that the AJP protocol was optimised between older IISs and Tomcat to help with this connection challenge. Maybe a good idea would be for Microsoft to allow some sub-modules within ARR via exposing an ARR Handler API to handle specific connections to certain servers, which will then be the logical place for the new Tomcat connector that will once again permit the use of AJP etc.

      I will check out the link fully so once again, thanks for making me aware of this.

      Regards,

      Dan

      Reply
    2. Gary

      We have implemented a Open Text Media Manager (v7.0.4) solution fronted by IIS 7.5/ARR and although this initially appeared to work well. However we found that during bulk asset loads via the user interface connection reset errors are seen and imports fail. In this scenario assets fail to copy from their source to the application working area. In an attempt to address this problem we have increased the Server farm Proxy Timeout, ISS Connection Time-out and disabled the ISS output cache, but this has not stopped the connection resets.

      Are there any other specific IIS/ARR or Tomcat parameters that we should also modify, e.g., timeouts, caches etc ?

      I note from Brandon’s entry “Not sure I like it as much on front-ending a tomcat instance though. Does not work well under load as both tomcat and arr really are not aware of each others load parameters. Leads to dropping of connections.” the issue of dropping connections between ARR & Tomcat. This I believe is the issue we are seeing in our implementation.

      Has anyone else seen connection reset issues between ISS/ARR & Tomcat/Open Text Media Manger and been able to resolve ?

      Your thoughts would be appreciated.

      BR,
      Gary

      Reply
      1. Danny Baggs

        Sorry to hear about your issues Gary. It is a worthwhile point and one that would be good to generate discussion on so I too would welcome input from those with greater expertise.

        Regards,

        Dan

        Reply
  10. Lance

    Danny,

    Thanks for the walk through it was very helpful. I have this working as described in your tutorial; but what if I need to have to instance of tomcat running, one on 8080 another on 8081 both on the same server. I need all requests to http://example.url.com/site1 to route to server1: 8080 and all request to http://example.url.com/site2 to route to server1: 8081. How can I set a rule up so iis can handle these request to one farm.

    -Lance

    Reply
    1. Danny Baggs

      Hi Lance,

      I would advise to perhaps set up two farms, each with one of the servers in and then you can configure the server level rewrites based on the paths you’ve detailed.

      Hope that helps.

      Dan

      Reply
      1. G

        Thank you for the great tutorial!

        I’m trying the same thing as Lance and cannot get it to work.. I have two Tomcat instances on the same app server, say appserver:8080 and appserver:8081. Both instances are running the same app and therefor use the same contexts to access the app.

        I have setup two server farms, one for each of the app servers, pointing to appserver and set the httpPort for 8080 and 8081 respectively (hitting enter so it’s bolded/committed before hitting Add).

        For the URL rewrite rules, I have two rules, one for each farm: Matches wildcard, pattern: prefix1/* or prefix2/* respectively, routing to server farm http://farm1/{R:0} or http://farm2/{R:0} respectively.

        I’m hoping that this should then route a request to http://webserver/prefix1/path/to/app to http://appserver:8080/path/to/app — is this correct?

        When I attempt to access http://webserver/prefix1/path/to/app, I get a 404. Attempting http://webserver/prefix1 gets me a 404, not the Tomcat splash as I’d expect. Restarting IIS hasn’t helped, logs don’t show me much besides the URL requested and the 404 sent back.

        What am I doing wrong?

        Reply
  11. IB

    Man you are a life saver… I intially setup the environment for Adobe Robohelp using ARR as pass through proxy to Tomcam with a URL rewrite. It was working fine for IE9 only, Firefox and Chrome used to get stuck in some kind of a loop.
    I’ve implemented it again using your method, and it works like gold.

    Thanks heaps, I didn’t knwo that you can use the server farm function in this way. The Jakarta ISAPI drove me crazy on the 64 bit environment. It just stops working.

    I will try to drop some pressure on it this week to see if it’s gonna break.

    IB

    Reply
    1. Danny Baggs

      Hi Ibrahim,

      Thanks for taking the time to provide feedback.

      Drop a comment back here for the results of the comparative tests you’re doing. Would be great to know.

      Regards,

      Dan

      Reply
  12. Andrew

    Hi, I enjoyed reading the article but I have a problem that perhaps you haven’t run into with your setup. I have Tomcat 7 installed along with iis7, of course. The instructions you have work perfectly for redirecting a request for the IIS https (default 443 port) of a certain directory “dir(.+)” to Tomcat’s https port (8443) and rendering a jsp page. So, the request would look like https://example.server.net/dir/index.jsp and it would be translated to https://localhost:8443/dir/index.jsp. However, if I were to output the session ID to the screen on that index.jsp page, I would see something like 9F236F55F393CECEFE67545699EB8673 and upon hitting the refresh button in my browser would see a brand new id of say 4AE00E12D646BBD963A1B9117BA888B1.

    I have tried setting session parameters in the jsp page and then immediately calling them from session and outputting values, successfully. I have also tried visiting the jsp page directly at port 8443 and have confirmed that the session id is not reassigned. So, I believe it must have something to do with the server farm or the url rewrite rule or a setting in the arr. I am thinking the necessary client identifiers never reach Tomcat so it thinks every request is from a new client, but I have no idea why not. It is better than what I was afraid of when I started; that every client hitting IIS would end up sharing the same session with Tomcat. But it is still something that must be resolved to make this viable. No one else on the internet seems to have this issue. Maybe I have something uniquely messed up. I appreciate the effort you have put into disseminating this information, it has been a great tutorial. Thanks for your help!

    Reply
    1. Danny Baggs

      Hi Andrew,

      There are a couple of things that come to mind with your challenge:-

      1) It may be obvious but have you tried different browsers? Could cookies be completely disabled in the browser you are testing with? I believe by default, servlet containers use session cookies for the session key by default so this is why it is the first thing to check in my opinion.

      I’ve also had the experience before where certain HTTP headers were being stripped out of my requests by a firewall or equivalent server that lay between my client and server. That was a particularly frustrating one to work out but to be fair, was filtering the HTTP “Accepts” header and not cookies.

      2) This is just an unrelated observation and I may be wrong on this one but if the connection from your client to IIS is secure through HTTPS, there is no need to pass that on using HTTPS to tomcat. IIS is the front controller and trust exists between IIS and Tomcat so it feels unnecessary.

      Hope this helps and feel free to comment back here if the above suggestions do not make sense or don’t help at all. Equally, if they help, then it would be great to know also.

      Regards,

      Dan

      Reply
      1. Jason

        Hi Dan,

        Great articles! I have been using them as examples for our new Windows environment. I had follow every step and was able establish a connection between IIS 7 and Tomcat 7 via ARR. So we have removed the :8080. Now I need to make the URL address to a friendlier address. We are using OpenText Delivery Server 11.0, which outputs an ugly URL address. I have tried the last week to figure out how to setup a rewrite rule through IIS ARR to convert this URL (dev2.[domain].com/cps/rde/xchg/[project]/hs.xsl/index.htm) to (dev2.[domain].com/index.htm). I have used the following patterns at both the server URL level and at the site level in ISS.

        – ([^/]+.html?)
        – cps(.+)

        And the following actions:

        – /{R:0}
        – /cps/rde/xchg/merrilldirect/hs.xsl/{R:1}

        When I browser to dev2.[domain].com/index.htm, I get a 400 error. But when I goto dev2.domain.com/cps/rde/xchg/project/hs.xsl/index.htm, I get the page.

        Would have any suggestions as to why this is not connecting up?

        Great appreciate the help!

        Jason

        Reply
        1. Danny Baggs

          Hi Jason,

          We’re doing 2 separate things here and there is a little trade off that goes with it.

          First of all, we are setting up the IIS server to re-route requests to delivery server that conform to a certain path pattern. This should be managed by setting up the rules for the server farm, which in turn adds a rewrite rule to the server level. The fact that you get the page for dev2.domain.com/cps/rde/xchg/project/hs.xsl/index.htm implies this part is configured ok. However, I would not try and do any rewriting as part of that rule – i.e. the cps(.+) rule should have the action to “Route to server farm”, choose the Delivery Server farm and set the path to /{R:0}.

          The other thing we are doing is the the URL “cleanup”. This doesn’t need to be at server level and in actual fact, shouldn’t be. You could have multiple sites set up within an IIS instance and keeping the server level rewrites abstract and the site level re-writes specific allows you to map different IIS sites to different Delivery Server projects.

          Therefore the ([^/]+.html?) rule should be added to the site level and should be a ‘rewrite’ action but with the key difference that you should put in an absolute URL. e.g. http://localhost/cps/rde/xchg/project/default.xsl/{R:1}. This is what then triggers the reverse proxy that I mention in my 22nd June 2011 update at the top of the article.

          What this now means, is that the request is kind of processed twice (the trade off I mentioned above). The “clean” URL http request is received by the server e.g. http://www.domain.com/index.htm, which matches no server level rules (as there is no ‘cps’ in the path) and the domain name maps the request through to the relevant IIS site (or just the default if just one). At the site level, the path string matches the html rewrite rule we’ve set up and therefore the request URL is rewritten with the longer “ugly” URL but to the localhost domain. This essentially sends the newly formed request through the server again. This second pass through the server level rewrites matches the ‘cps’ rule and therefore that request is delegated to the server farm.

          Hope that helps,

          Dan

          Reply
  13. Andrew

    Ok, sure, trying out your recommendations:
    1.a. Different browsers: checked IE, same results as firefox, neither have cookies disabled
    1.b. firewalll: well, only port 443 is accessible outside per business requirements, tried adding in and outbound rules for localhost 8443. Same result.
    2. Changed the iis inbound rewrite rule to http:// instead of https:// before the server farm of Tomcat – Delievery Server, path is still /{R:0}. Same result.

    Others have made the decision to just bind tomcat and iis to separate ip addresses. Thanks for the help, I may get time to make an academic pursuit of this. :)

    Reply
  14. Andrew

    By accident I identified my problem. After temporarily turning off IIS I observed the session ID was still being reset. I happened to be refreshing the same jsp page I had loaded to test earlier with the ARR rewrite. The problem was an extra “/” between the host and the uri. My url read “https://example.server.net//dir/index.jsp”. Removing the slash to get ” https://example.server.net/dir/index.jsp” resulted in retaining the same session id. I’ve never seen a server do that before, had no idea it was possible to get that behavior. It appears to be what Tomcat wants to do with an extra slash. I tried it a couple times with each address to make sure I wasn’t seeing things. Sorry to fill up your blog! Thanks again for your help.

    Reply
  15. Aruna

    Hi

    I am trying to configure ARR and tomcat in cloud to maintain session affinity. Over here i would be knowing the IP addresses of my tomcat instances in runtime. So do you have any idea how to configurre this

    Thanks,
    Aruna

    Reply
    1. Danny Baggs

      Hi Aruna,

      Sorry for the late reply. Off the top of my head, I wouldn’t really know unless you modified one of the IIS config files direct. Another option (but would probably still require a restart of the IIS service) is to map the IP addresses to names that you put in the local windows hosts file and then the config in IIS can be consistent by using the names. The challenge then would be to change the hosts file through a tool to the known IP addresses as and when.

      Like I say, this is a long shot and I’m very skeptical that it would work. Perhaps post in the IIS forums about this one as those more knowledgeable than I on IIS will be able to give a better answer.

      Regards,

      Dan

      Reply
  16. Ashis Kumar Rout

    Dan,

    I am doing a SSO implementation, where the main application is deployed in IIS and got a link and eventually that link to be redirects to another server where the application deployed on the Tomcat. Now if i use AJP, i could do the redirection and the user id passed with the request. same thing i can acheive using the ARR, but i dont get the user name in the request header, what could be the possible reason if anyone can help.

    rout.ashis@gmail.com

    Reply
    1. Danny Baggs

      Hi Ashis,

      I’m afraid I wouldn’t know of the top of my head unless I spent some time to look into it.

      Perhaps someone else comes by your comment and can shed some light on this.

      Regards,

      Dan

      Reply
  17. Joo

    Hello,

    I have created a routing rule in ARR. Please see the rule below
    =================
    Pattern – ([^/]+.pdf?)
    Action Properties –
    Scheme: http://
    Server farm: DS – Tomcat Redirection
    Path:/cps/rde/xbcr/project/{R:1}
    ==================

    This is working fine, but when the rule is enabled in ARR, any pdf documents is IIS are not accessible on our website. However, when I disabled the rule in ARR, then PDF documents in IIS are accessible, but PDF documents in Delivery Server are not accessible. Can you please advise me how this issue can be resolved?

    Regards,
    Joo

    Reply
    1. Danny Baggs

      Hi Joo,

      You’ve kind of answered your own question. The incoming request URL witin the rule is blindly taking all requests for files ending in .pdf and delegating that request to the Delivery Server. By that same theory, it is not going to even look in the local IIS folder. In other words, you can’t have your cake and eat it. The URLs for each type of pdf resource need to differ in pattern in the same way that they would need to differ if they were two separate directories.

      I would recommend making a distinction between the two types of pdf resources and publish them accordingly. For example, within the Management Server, you can set the virtual path for the pdf’s folder that are to go into Delivery Server, this will then give them a distinctive path i.e. /ds_pdfs/.pdf. Then, you can adapt your rewrite rule to be more specific for this scenario, which will omit the pdf’s that are on the IIS filesystem and therefore they will be served as usual.

      Hope this helps,

      Dan

      Reply
    1. Danny Baggs

      Hi Rohit,

      I’m afraid the short answer is that I simply don’t know. I’ve not come across this problem before and in truth am no IIS expert.

      As I’ve done on a couple of occasions before, I’ll stand back and hope that others more knowledgeable than me may come across this article and comment to help you.

      Regards,

      Dan

      Reply
      1. Brian

        Hi Danny,

        I’m experiencing the exact same issue. Sessions are being mixed up between two users and it causes content meant for one user to be displayed for another. Have you come across anything like this before?

        Reply
  18. Toni

    Hi Danny,

    We have ASP.NET web application running on port 80, and Java web application running on 8086. The problem is that customers who use those applications, can communicate only with port 80 because their policy doesn’t allow them to communicate with non-standard ports. I can change the port of Java application, but not of the ASP.net application. Can I achieve that customers can reach both applications trough port 80? For example
    ASP.NET is on http://www.mydomain.com:80/app1
    Java is on http://www.mydomain.com:80/app2

    Thank you,
    Toni Mofardin

    Reply
  19. Danny Baggs

    Hi Toni,

    As far as I understand it, yes you should be able to do that if you configure the main routing rule to delegate all requests that match the app2 structure to your java app.

    Dan

    Reply
  20. Felix Lindemann

    Dear Danny –
    Thank you for this paper. In the end it worked for me – almost. I had to redefine the serverfarm and explit giving the IP 127.0.0.1 to Tomcat.

    I was then experimenting with the examples with the aim to point to some application using a subdomain or different website…

    I’ve set up an action with /examples/{R:0} as path pointing at tomcat.

    The problem occurs after clicking servlets and in the next menu any app – here helloworldexample.

    The problem is, that for some reason “examples” will be doubled
    /examples/examples/servlets/servlet/HelloWorldExample
    and the page can’t be resolved.
    Following the jsp branch the same happens:
    HTTP Status 404 – /examples/examples/jsp/jsp2/el/basic-arithmetic.jsp

    Do you have an idea, what I’m doing wrong, or what I haven’t thought of…
    Thanks in advance. Felix

    Reply
    1. Danny Baggs

      Hi Felix,

      Could it be as simple as you don’t need the ‘examples’ part in your rewritten action?

      Regards,

      Dan

      Reply
      1. Felix Lindemann

        Hi, Thank you for your answer.
        I still think that I need this ‘examples’ part in the action.
        For my “real” deployed applications I want to have 2+ applications running on Tomcat, each adressed by a certain sub.domain.com.

        As far as I understood this architecture, this can be done by defining a rewrite rule for each app:

        app1.myDomain.com –> localhost:8080/app1
        app2.myDomain.com –> localhost:8080/app2
        myOtherDomain.com –> localhost:8080/app3

        As my apps are programmed in Spring MVC, they tend to have rather long urls. Currently I solved it by deploying only 1 app to myDomain.com – installing it as ROOT application on Tomcat.
        –> As things move on, the described scenario with 2+ applications has to be realised for the next project.

        Thanks in advance,
        Regards,
        Felix

        Reply
        1. Danny Baggs

          Hi Felix,

          I think I see where you are going now.

          It sounds like you need 3 “Route to server farm” server level rules that will be applied. All of these won’t differ from the pattern that is being matched but you can add Conditions to each rule. In this case, your conditions are based on a match of the ${HTTP_HOST} value. This is a little illogical unfortunately as it would make more sense to be able to set such “Route to server farm” rules at the individual site level and use separated virtual sites but alas, this is not available.

          Would that work?

          Regards,

          Dan

          Reply
          1. Felix Lindemann

            Hi Dan,
            Thank you very much for your reply.
            I’ve been testing this on the weekende in all variants.
            It seems as my server config is OK, but the applications config (Java-Spring) needs a package like TUCKEY in order to be able to understand the rewriting rules.

            When I am able to manage it the way it is supposed to be, I’ll write my experience together and post it here,

            Thanks again for your input!
            regards, Felix

  21. Manu

    Hi Dan,

    I have an interesting related scenario and I’d really appreciate if you can weigh in.

    Heres what the network architecture looks like:

    /—-> IIS_1 —-> Tomcat_1 (/cc, 8080)
    /
    LoadBalancer
    —-> IIS_2—-> Tomcat_2 (/cc, 8080)

    I have an application deployed on Tomcat server under application context /cc and port 8080

    I needed IIS because I am using windows authentication and passing the authenticated user as a cookie to the application on tomcat.

    I am able to get this to work but here is the issue:

    My loadbalancer gives me a URL like: http://app.company.com
    The IIS URL looks like: http://servername.company.com
    The Tomcat URL looks like: http://servername.company.com:8080/cc

    When I use ARR, I start with the URL http://app.company.com in the browser address bar but after the redirects it turns into http://servername.company.com:8080/cc (in the browser) after the URL rewriting. As a result all my subsequent requests are going directly to http://servername.company.com:8080/cc/* instead of going back to the load balancer. This has multiple issues:
    - Its the unfriendly server node URL that I don’t want my users to see
    - Secondly it doesn’t go through the load balancer and as a result I am using one single node for subsequent requests
    - Thirdly my authentication (windows auth) is on Tomcat. If the session times out, tomcat doesn’t know how to handle it.

    The user experience I expect is that the browser URL should remain unchanged (the load balancer URL should stay) and behind the scenes the request/response is passed back & forth from the load balancer to the IIS to Tomcat and back.

    I’m a little new to the the IIS Tomcat Integration and I’m wondering if this is even achievable via ARR. Any thoughts or suggestions? I’d greatly appreciate any recommendations.

    Thanks
    Manu

    Reply
    1. Danny Baggs

      Hi Manu,

      To start with, let me clarify how I’ve understood your setup:

      Node 1 – A load balancer which is the ‘front controller’ meaning that it is the first node a HTTP Request hits and all requests should go through its http://app.company.com URL.

      Nodes 2 & 3 – Each host IIS and Tomcat with Tomcat running on its default port within the context of /cc.

      I’m making the assumption that your load balancer is providing “sticky sessions” and therefore consistently routing traffic to the same IIS/Tomcat node for a given session.

      I’m also making the assumption that you’ve set up a routing rule for your server farm within ARR (each containing just the one Tomcat server behind) that matches on some wildcard pattern so that all traffic is re-routed to the Tomcat cc context.

      First of all, I think your redirect instead of re-route issue may be because of a small omission that caught me out too. I believe you need to enable your ARR setup to act like a reverse proxy. Check out the update I added at the top of the post on the 22nd June 2011. Without this ‘Enable Proxy’ checkbox checked, I too was experiencing redirection instead of re-routing.

      As long as your not hard-coding any absolute URLs within your application, then the above ‘fix’ would make any subsequent links and therefore requests go through the load balancer http://app.company.com. An extra word of caution on this point is that the writing of the cc context in any links within the app would not be desired I guess.

      Lastly, if the above works then all requests will be following the route you need them to and therefore they shouldn’t reach the Tomcat instances without that important authentication information.

      Let me know how you get on.

      Regards,

      Dan

      Reply
  22. Jonas Engedal

    Hi Danny

    Thanks for your time spent on answering questions.

    My problem is when I try to access the Tomcat manager and is prompted for credentials I get to a loop where I repeatedly are asked for credentials. The same problem occurs when accessing another application with authentication.
    Going to the Tomcat root page is no problem. Hope you can help.

    Regards

    Jonas

    Reply
    1. Danny Baggs

      Hi Jonas,

      I’m afraid I don’t know too much about that and I’m a little rusty nowadays.

      I may be clutching at straws here but could this be an issue with the session cookie set for Tomcat? The theory goes that you can access multiple pages when you are not logged in but each request may be part of its own session and you would not be any wiser (until you get memory issues). Once you log in however, it is only that session that is authenticated and therefore that could be the cause.

      Is the Tomcat session cookie (I think called JSESSIONID from memory) configured to be set against the correct outer domain? i.e. the domain that the IIS instance serves?

      Hope that helps,

      Regards,

      Dan

      Reply
  23. Mark Gunnell

    Dan,
    This is a great article as there isn’t much info out here regarding IIS and Tomcat. We’ve got a problem over here and I was hoping you may have come across it in your travels.

    Our application stack looks like:
    User
    Internet
    F5 (external)
    IIS 7.5 <– 3 iis7 proxies
    F5 (internal)
    Tomcat app <– 6 tomcat app servers
    DB

    We are not using "IIS Server Farm" function on our Reverse Proxy (with ARR). The Inbound Rewrite rule basically grabs the

    traffic with a specific HTTP_HOST and "rewrites" it to our internal F5 load balancer. That F5 is supposed to load balance

    and maintain session for the 6 Tomcat app servers.
    However, the users are experiencing session issues. Since JSesssionID seems to be getting stripped out by IIS, the user gets

    the popup error "site requires cookies to be enabled". Also sometimes a user will bounce from app server to app server unnecessarily while changing screens within the app.

    Earlier we had the "underscore in the domain name" problem. After overcoming that, we are having this issue now…

    The F5 team postulates that these issues are caused because the IIS isn't maintatining session using the same variable that Tomcat uses – specifically "JSessionID".

    Do you know how we can have IIS maintain that session using the JSessionID?

    (I hope this explanation paints a thorough picture)

    I found something earlier that mentions and "Outbound Rule" or something. Data on the internet has been difficult to put together.

    Thank you in advance for any thoughts you may have on this.

    Kindest regards for your contributions to the Community,

    Mark

    Reply
    1. Danny Baggs

      Hi Mark,

      On the face of it, this sounds similar to the last comment I posted here but I have to admit that it has been many years now since I played with Tomcat settings so I cannot be sure.

      What I do know whoever, is that Tomcat sets the JSESSIONID session cookie as you mention. What I don’t know is whether this gets set to a default domain or path etc that doesn’t take into consideration the rewrites that are going on upstream. Therefore, it could be that this does not get set for that reason (or one of the upstream servers or load balancers are stripping it out, which would be less likely).

      With regards to making sure that IIS maintains a “sticky session” to the same tomcat instance, I would encourage you to look at ARR Server Affinity settings under the specific Server farm (highlight chosen Server Farm, middle pane – Server Affinity – check box at top “Client Affinity”). Perhaps you can change the default ARRAffinity cookie name to JSESSIONID and that would do what you need.

      Hope that helps,

      Dan

      Reply
  24. mail_2_phil@yahoo.com

    Hi Danny,
    We have IIS 7.5 on windows 2008 R2 64 bit server and Tomcat 7. We used the ISAPI redirector and the performance is just painful. It is 15x slower going thru the ISAPI redirector vs going to Tomcat directly. We are in the process of going with the ARR to see if that improves the performance. Have you see anything like this where implementing using ARR significantly increases the performance vs using the ISAPI redirector.

    Thanks
    Phil

    Reply
    1. Danny Baggs

      Hi Phil,

      I’ve not witnessed any significant changes in my experience. If anything, the approach I’ve used with ARR actually should be a little less optimal as I use the reverse proxy to resend the request through the server again. This is all a trade off of course and one that in my opinion is worthwhile due to the ease in which the config can be managed within IIS7 itself.

      Regards,

      Dan

      Reply
  25. miuxa

    Just today we’ve solved a 401 issue in an ARR redirecting to a Tomcat 6 with waffle in another server, after some time of frustration. We noticed that the default website had anonymous and also impersonate, and although we disabled aspNet impersonate it kept setting itself up as enabled. It just stopped doing that with an IISreset command that fixed it.

    Reply
    1. miuxa

      Forgot to mention that we had to get rid of the web.config that had coded ‘impersonat=false’ that was supporting de ‘impersonate disabled’ and was an IIS ‘creation’. We ended up with no web.config in the default website folder, ‘impersonate disabled’ on features view of default website, and tomcat accepting our single signon. (IIS7, ARR,TOMCAT 6, Waffle).

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>