Search code examples
javaresttomcatjerseytomcat8

Is Tomcat 8 reading the web.xml and context.xml files in my Java Rest API (war)?


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>

Solution

  • Resolved the problem using both of the comments on this call.

    1. 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.

    2. 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

    3. 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 &quot;%r&quot; %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>