I created a Java Rest API (Dynamic Web) project in Eclipse (including Javax and Jersey libraries) and deployed it to my Tomcat 8 server.
It returns a basic JSON response when I call it via HTTP (e.g. http://www.mydomain.co.uk:8080/MyJavaProject/context_string/path_params
), but when I enable SSL/TLS on the server, with a genuine certificate, it gives a 404 Not Found
in Postman.
error.log
shows a file does not exist
error on /path/MyJavaProject/context_string/path_params
, but the file doesn't exist as it's a reference param in my REST API, so I don't think Tomcat knows to use the WAR file.
I can get to the directory structure navigator if I call https://www.mydomain.co.uk/MyJavaProject
.
My logs are all OK and show no errors now. I have put the security values in my web.xml
in my app's WEB-INF
. Permissions on the WAR
and its exploded folder are all 777
.
I have read that something called context.xml
is used in this area, but may or may not be used if autoDeploy-true
is set (mine is).
My question is: how can I find out if Tomcat is actually reading the context.xml
and web.xml
in my app? This is my last idea to try and resolve my 404 error.
Here is my app's web.xml
file:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>MyProject</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>ServletAdaptor</servlet-name>
<servlet-class>
com.sun.jersey.server.impl.container.servlet.ServletAdaptor</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletAdaptor</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>MyProject</web-resource-name>
<url-pattern>/context_string/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
</web-app>
Here is my app's context.xml
file:
<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="" path="" reloadable="true">
</Context>
Resolved the problem using both of the comments on this call.
There was a port conflict, so i changed both server.xml and apache2/../000default.conf to use 8443 (i found 443 temperamental). Going along with this, i include '8443' as the port in all my URL calls now, rather than no port.
I added this to .conf file:
SSLProxyEngine on
ProxyPass /MyProject/context https://www.mydomain.co.uk/MyProject/context
ProxyPassReverse /MyProject/context https://www.mydomain.co.uk/MyProject/context
Had to also a2enmod proxy_http and set VirtualHost tag to be ip and not '*', ie ipaddress.8443 and for good measure, check it works using
apache2ctl configtest
I didnt really do much more with the web.xml in my app and i removed the context.xml from my app.
It was really a case of tweaks the knobs and dials until it worked, and took me about 2 weeks. Why can't it be easy.
Here are my files for reference
apache2/..conf
<VirtualHost ipaddress:8443>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<IfModule dir_module>
DirectoryIndex index.html
</IfModule>
LogLevel debug
#SetEnv HTTPS on
SSLEngine on
SSLCertificateFile /etc/ssl/certs/mydomain_co_uk.crt
SSLCertificateKeyFile /etc/ssl/private/www.mydomain.co.uk.key
# SSLCertificateKeyFile /etc/ssl/certs/mydomain_co_uk.pem
SSLCACertificateFile /etc/ssl/certs/mydomain_co_uk.ca-bundle
ServerName www.mydomain.co.uk
SSLProxyEngine on
ProxyPass /MyProject/context https://www.mydomain.co.uk/MyProject/context
ProxyPassReverse /MyProject/context https://www.mydomain.co.uk/MyProject/context
Alias /ProjectName"/var/lib/tomcat8/webapps/ProjectName"
<Directory "/var/lib/tomcat8/webapps/ProjectName">
Options Indexes FollowSymLinks
AllowOverride all
Allow from all
</Directory>
<Location />
Require all granted
</Location>
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>
Server.xml
<Connector
protocol="org.apache.coyote.http11.Http11AprProtocol"
port="8443" maxThreads="200" clientAuth="false"
scheme="https" secure="true" SSLEnabled="true"
SSLCertificateFile="/etc/ssl/certs/mydomain_co_uk.crt"
SSLCertificateKeyFile="/etc/ssl/private/www.mydomain.co.uk.key"
SSLPassword="planetx"
SSLVerifyClient="optional" SSLProtocol="TLSv1+TLSv1.1+TLSv1.2"/>
<Engine name="Catalina" defaultHost="localhost">
<!--For clustering, please take a look at documentation at:
/docs/cluster-howto.html (simple how to)
/docs/config/cluster.html (reference documentation) -->
<!--
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
-->
<!-- Use the LockOutRealm to prevent attempts to guess user passwords
via a brute-force attack -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the Realm. -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
web.xml from my apps web-inf
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>Projectname</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>ServletAdaptor</servlet-name>
<servlet-class>
com.sun.jersey.server.impl.container.servlet.ServletAdaptor</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletAdaptor</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>Projectname</web-resource-name>
<url-pattern>/context</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
</web-app>