Fixing deep linking issue – Deploying angular application on Tomcat server
Angular (2+) supports two types of Routing Strategies – HashLocationStrategy
and PathLocationStrategy
. PathLocationStrategy
is the default configuration when you build an application using the angular CLI. PathLocationStrategy
is having lot of advantages over the HashLocationStrategy
and is the recommended configuration which is discussed in the docs here. This post explains how to use PathLocationStrategy
in angular application and deploy it on apache tomcat.
The drawback of PathLocationStrategy
is that it needs specific configuration to be done at the server side. If this configuration is not done at the server end, then it leads to 404
when deep links are accessed directly. Also this configuration depends on which server is being used. The main idea is that whenever there is a request for deep links, the server has to return back (or redirect to) index.html
of angular application. Then the index.html
will request for angular javascript files and then angular will take over the routing to the specific component at the client side itself.
Setting this redirect rule (or fallback to index.html
) for various servers like Apache, Nginx, IIS, GitHub pages and Firebase hosting is mentioned here in the angular docs. Unfortunately this doc does not cover the configuration for Apache Tomcat server. In this post we will cover setting the PathLocationStrategy
for a demo angular application and its server side configuration for Apache Tomcat server.
Demo
For the demo purpose I have create a sample angular application using the CLI and have uploaded the code on github here.
This application consists of 2 components – HelloWorldComponent
and HelloUniverseComponent
which are linked to paths "world"
and "universe"
respectively. The PathLocationStrategy
is the default configuration. Also by default <base href="/">
is set in index.html
which we do not change. Below are the routing configurations and the index.html content –
~/src/app/app-routing.module.ts -
...
const routes: Routes = [
{ path: 'world', component: HelloWorldComponent },
{ path: 'universe', component: HelloUniverseComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
~/src/index.html -
...
<head>
<meta charset="utf-8">
<title>TomcatDeploymentDemo</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
...
These are the only setup needed (which is set by default by CLI) on the client side of the application. To build and deploy the demo application on tomcat in the context path – “hello
“, make use of the --base-href
option of ng build
command as below –
ng build --base-href /hello/
This will generate the build under ~/dist/tomcat-deployment-demo
directory. Copy all the files under this to the tomcat server location – ~/webapps/hello
and start the tomcat server. I have my tomcat running on local machine on port 8080. The application can now be accessed with the URL – http://localhost:8080/hello
as seen below –
Deep linking issue
Deep linking issue is when you hit the deep links inside the angular application (http://localhost:8080/hello/world
and http://localhost:8080/hello/universe
), but the server returns 404
instead of the angular application as seen below –
Solution
The solution for this is to setup the tomcat to redirect any deep links of the angular application (ie. http://localhost:8080/hello/*
) to point to the index.html
of the application (ie. http://localhost:8080/hello/index.html
). This involves 2 steps –
- Configure the RewriteValve in server.xml
- Write the rewrite rule in rewrite.config
1. Configure the RewriteValve in server.xml
Edit the ~/conf/server.xml
to add the below Valve inside the Host section as below –
...
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
...
</Host>
...
2. Write the rewrite rule in rewrite.config
Create directory structure – ~/conf/Catalina/localhost/
and create the rewrite.config
file inside it with the below content –
RewriteCond %{REQUEST_PATH} !-f
RewriteRule ^/hello/(.*) /hello/index.html
After setting this up restart the tomcat server and you can hit the deep links of the application which will route to the correct components inside the angular application.
19 thoughts on “Fixing deep linking issue – Deploying angular application on Tomcat server”
Hey just wanted to give you a quick heads up. The text in your
content seem to be running off the screen in Internet explorer.
I’m not sure if this is a format issue or something to do with web browser compatibility
but I figured I’d post to let you know. The style and design look great though!
Hope you get the issue resolved soon. Kudos
Thanks for letting me know. Will try to fix the IE issue.
Hi Nithin,
Your solution is working but it is always redirecting to landing page of the angular application instead of requested url
Hi Rahul, I cannot help without more information. But this may be because your application is not storing the session. So next time when you directly access the deep link, it thinks you are not logged in and is probably redirecting you to the login/landing page.
Awesome article.
Way cool! Some very valid points! I appreciate you penning this post and also the rest of the website is
also really good.
Thanks for your marvelous posting! I certainly enjoyed reading
it, you are a great author. I will remember to bookmark your
blog and will often come back sometime soon. I want to encourage
you continue your great posts, have a nice day!
Hey very nice blog!
Keep this going please, great job!
I must thank you for the efforts you have put in penning this website.
I really hope to check out the same high-grade content from you in the future as well.
In truth, your creative writing abilities has inspired me
to get my own, personal website now π
Great article! Thank you π
Hi Nithin,
I am using Tomcat 7.0.81. above solution doesn’t working for version 7.
Could you please help me with this. My Angular version is 4
Thanks in Advance.
Hi Neetesh, you can try this out. I do not have a setup currently to verify it. Maybe you can try it and post your findings here.
Hey Nithin,
Thanks a lot, your solution helped a lot in resolving this major problem and it is working on IE, Chrome very smoothly.
Also it would be great help if you give some guidelines about how to use DOMAIN name to access website instead of localhost server ip as I am not getting any solution for this in angular app.
If you want to use domain name on your local setup, then you can make appropriate host file entries for that.
Great article, many thanks.
Hi, thanks. Do you know how to deploy some angular apps in the same tomcat?