title: Call method in one webapp from another in a Tomcat instance
body: <p><strong>The problem:</strong>
  I have a Java webapp running in a Tomcat instance, and a second JSP webapp, JReport, in the same Tomcat instance. I need to use JReport to generate a report, and then send the results to the primary webapp as securely as possible/reasonable.</p>
  
  <p>I'd like to use encrypted DB IDs that depend on a Tomcat session, but I'd settle for unencrypted IDs or temporary tokens. Some quick research (read: Googling) has told me that this should be possible with Tomcat cross-context.</p>
  
  <p><strong>The possible solution:</strong> <a href="https://blog.imaginea.com/cross-context-communication-between-web-applications/" rel="nofollow noreferrer">This webpage</a> gives some brief instructions for calling a method between two webapps using the Spring framework. Neither my webapp nor JReport uses Spring that I'm aware of, so I'm having trouble figuring out how to apply the code sample to my code.</p>
  
  <p><strong>The code:</strong> This code is adapted from the example on the page linked above. There are two places where I don't know what parameters to put into function calls:</p>
  
  <pre><code>private void sendPdf(HttpServletRequest request, String custCode, int reportId, int documentId, byte[] data) {
      ServletContext srcServletContext = request.getSession().getServletContext();
  
      // Where does this parameter come from???
      ServletContext targetServletContext = srcServletContext.getContext("/Bar");
  
      //save the class loader which loaded the 'Foo' application in a variable
      ClassLoader currentClassLoader = Thread.currentThread().
      getContextClassLoader();
  
      try {
          // What attribute name to put here???
          Object object = targetServletContext.getAttribute
          ("org.springframework.web.servlet.FrameworkServlet.CONTEXT.bar");
  
          // Get the class loader for Yawl and set it as the current class loader
          ClassLoader targetServiceClassLoader = object.getClass().getClassLoader();
          Thread.currentThread().setContextClassLoader(targetServiceClassLoader);
  
          // Get the ReportSigner class and its static method
          Class&lt;?&gt; reportSignerClass = (Class&lt;?&gt;) targetServiceClassLoader.loadClass("com.procentive.yawl.logic.report.ReportSigner");
          Method targetMethod = reportSignerClass.getMethod("addReportPdf", String.class, Integer.class, Integer.class, byte[].class);
  
          // Invoke the static method on ReportSigner
          targetMethod.invoke(null, custCode, reportId, documentId, data);
      } catch (Exception e) {
          e.printStackTrace();
      } finally {
          // Revert to original class loader
          Thread.currentThread().setContextClassLoader(currentClassLoader);
      }
  }
  </code></pre>
  
  <p>This is my app's context.xml (also adapted from the same page):</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;context cookies="false" override="true" crossContext="true"&gt;
      &lt;WatchedResource&gt;WEB-INF/web.xml&lt;/WatchedResource&gt;
  &lt;/context&gt;
  </code></pre>
  
  <p><strong>The question:</strong> What's the context name that I put into getContext() on line 5? What's the attribute name that I put into getAttribute() on line 14? Is this the right way to go about inter-webapp communication? Or would it be better/easier/more secure to do something else entirely?</p>
  
  <h2>Update</h2>
  
  <p>After some difficulties getting JReport to run the new code, I'm finally able to test this. I followed the example of <a href="https://stackoverflow.com/a/19273868/2444020">this answer</a> from another question, and am trying to use a servlet and RequestDispatcher.</p>
  
  <p>Relevant code (yawl_server is the app getting called; jreport is the app doing the calling):</p>
  
  <p>Tomcat server => server.xml (possibly rendering yawl_server => context.xml redundant?):</p>
  
  <pre><code>&lt;Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true"&gt;
      &lt;Context docBase="yawl_server" path="/yawl_server" crossContext="true" reloadable="true" source="org.eclipse.jst.jee.server:yawl_server"/&gt;
  &lt;/Host&gt;
  </code></pre>
  
  <p>jreport => Servlet:</p>
  
  <pre><code>ServletContext context = getServletContext().getContext("/yawl_server");
  RequestDispatcher rd = context.getRequestDispatcher("/reportsign");
  rd.forward(request, response);
  </code></pre>
  
  <p>When I reach this code, context is always null, despite the two apps (supposedly?) running in the same virtual host and the argument to getContext() matching the path attribute of the context. What am I doing wrong?</p>