Aufruf eines Servlets mittels ServletContext

Hallo alle zusammen,

ich suche nach einer Lösung um nur mittels des ServletContext(es) ein Servlet aufzurufen.
Wie das prinzipiell geht ist mir bekannt.
Jedoch will ich das nicht aus einem anderen Servlet aufrufen, sondern aus einer Klasse die erstmal nur den SevletContext kennt. Ich habe somit kein ServletRequest- bzw. ServletResponse-Objekt.
Gibt es eine einfache Möglichkeit diese zu erstellen (habe bisherkeine gefunden)? Im Grunde würde bei Request die URI und die Methode reichen, beim Response der OutputStream.

Der Hintergrund ist, dass ich einen meiner Services selbst aufrufen will. Jedoch nicht via HTTPClient, da ich dort meine Deploy-Domain und meinen Port kennen müsste.

Hat jemand eine Idee? Wenn nicht was wäre der WorkAround?

Gruß
meinereiner
 

Thomas Darimont

Erfahrenes Mitglied
Hallo,

ja ich habe da einen "Workaround" - eine Variante über JMX- das Beispiel ist speziell für Tomcat, jedoch sollte sich das Verfahren bei anderen Servlet-Containern analog implementieren lassen:
Java:
package de.tutorials.app.web.util;

import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.URL;
import java.util.Scanner;

import javax.management.MBeanServer;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.servlet.ServletContext;

public class LocalServletInvoker {
	public void invoke(ServletContext servletContext, String servletUrlPattern) {
		try {
			int port = detectLocalCatalinaHttpPort();
			String host = InetAddress.getLocalHost().getCanonicalHostName();
			URL servletUrl = new URL("http", host, port,servletContext.getContextPath() + servletUrlPattern);
			Scanner scanner = new Scanner(servletUrl.openStream());
			while (scanner.hasNextLine()) {
				System.out.println(scanner.nextLine());
			}
			scanner.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private int detectLocalCatalinaHttpPort() {
		int localPort = -1;
		try {
			MBeanServer pms = ManagementFactory.getPlatformMBeanServer();
			ObjectName protocolHandlerObjectNamePattern = new ObjectName("Catalina:type=ProtocolHandler,port=*");
			for (ObjectInstance oi : pms.queryMBeans(protocolHandlerObjectNamePattern, null)) {
				try {
					if ("org.apache.coyote.http11.Http11Protocol".equals(pms.getAttribute(oi.getObjectName(), "modelerType"))) {
						localPort = (Integer) pms.getAttribute(oi.getObjectName(), "localPort");
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return localPort;
	}
}

Gruß Tom
 
Hallo,

danke für den Tipp! Funktioniert ohne Probleme!

Allerdings habe ich bei der Methode wie hier die URL ermittelt wird noch eine Frage (auch wenn sie nicht zum Topic passt):

Gibt es auch eine Möglichkeit auf diesen Weg die Servlet-URLs auszulesen? Normalerweise kann man das via des ServletContext machen aber nicht wenn man auf eine Uraltversion von EE (5) festgeschrieben ist.
Bisher habe ich unter Java EE 5 naemlich noch keinen Weg gefunden entweder das URL-Pattern eines via web.xml festgelegtes Servlet Servlet herauszufinden, noch ein Servlet via Code einzubinden.

Gibt es auf diesem Weg eine Lösung?

Gruß
meinereiner
 

Thomas Darimont

Erfahrenes Mitglied
Hallo,

das könnte man evtl. wieder via JMX rausbekommen - dann allerdings Servlet Container spezifisch - welchen ServletContainer verwendest du denn?

Gruß Tom
 
Hi,

ich bin mir nicht ganz sicher:
Ich verwende einen jBoss 5 (jboss-web) als Application Server. Ich bin nicht sicher, was dieser als default verwendet ...

Wie finde ich das im Detail raus?

Sorry für meine Unwissenheit!

Gruß
meinereiner
 

Thomas Darimont

Erfahrenes Mitglied
Hallo,

hier mal eine Variante für JBoss 5.0.1GA getestet, hier Prototypisch als ServletContextListener definiert:
(Die Klasse org.jboss.mx.util.MBeanServerLocator findest du in: ....jboss-5.0.1.GA\client\jboss-j2se.jar)
Java:
package de.tutorials.web;

import java.util.Arrays;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.management.MBeanServer;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class BootstrapListener implements ServletContextListener {
	public void contextInitialized(final ServletContextEvent sce) {
		
		//We have to wait some time for the server to come up...
		Executors.newSingleThreadScheduledExecutor().schedule(new Runnable() {
			@Override
			public void run() {

				try {
					System.out.println("trying to find servlet mappings:");

					ObjectName servletMbeansQuery = new ObjectName(
							"jboss.web:J2EEApplication=none,J2EEServer=none,WebModule=//localhost"
									+ sce.getServletContext().getContextPath()
									+ ",j2eeType=Servlet,*");
					MBeanServer mbs =
					// we have to use the JBoss MBeanServer instead of
					// ManagementFactory.getPlatformMBeanServer();
					org.jboss.mx.util.MBeanServerLocator.locateJBoss();
					Set<ObjectInstance> servletMbeans = mbs.queryMBeans(
							servletMbeansQuery, null);
					System.out.println(servletMbeans);
					for (ObjectInstance servletMbean : servletMbeans) {
						String[] mappings = (String[]) mbs.invoke(
								servletMbean.getObjectName(), "findMappings",
								new Object[0], new String[0]);
						System.out.println("Servlet: "
								+ servletMbean.getObjectName());
						System.out.println("Mappings: "
								+ Arrays.toString(mappings));
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}, 10, TimeUnit.SECONDS); 
	}

	public void contextDestroyed(ServletContextEvent sce) {
	}
}

Ausgabe:
Code:
...
02:59:27,920 INFO  [STDOUT] trying to find servlet mappings:
02:59:27,923 INFO  [STDOUT] [org.apache.tomcat.util.modeler.BaseModelMBean[jboss.web:j2eeType=Servlet,name=default,WebModule=//localhost/de.tutorials.web.test,J2EEApplication=none,J2EEServer=none], org.apache.tomcat.util.modeler.BaseModelMBean[jboss.web:j2eeType=Servlet,name=TestServlet,WebModule=//localhost/de.tutorials.web.test,J2EEApplication=none,J2EEServer=none], org.apache.tomcat.util.modeler.BaseModelMBean[jboss.web:j2eeType=Servlet,name=AnotherTestServlet,WebModule=//localhost/de.tutorials.web.test,J2EEApplication=none,J2EEServer=none], org.apache.tomcat.util.modeler.BaseModelMBean[jboss.web:j2eeType=Servlet,name=jsp,WebModule=//localhost/de.tutorials.web.test,J2EEApplication=none,J2EEServer=none]]
02:59:27,923 INFO  [STDOUT] Servlet: jboss.web:j2eeType=Servlet,name=default,WebModule=//localhost/de.tutorials.web.test,J2EEApplication=none,J2EEServer=none
02:59:27,923 INFO  [STDOUT] Mappings: [/]
02:59:27,923 INFO  [STDOUT] Servlet: jboss.web:j2eeType=Servlet,name=TestServlet,WebModule=//localhost/de.tutorials.web.test,J2EEApplication=none,J2EEServer=none
02:59:27,923 INFO  [STDOUT] Mappings: [/TestServlet, /A, /B, /C]
02:59:27,923 INFO  [STDOUT] Servlet: jboss.web:j2eeType=Servlet,name=AnotherTestServlet,WebModule=//localhost/de.tutorials.web.test,J2EEApplication=none,J2EEServer=none
02:59:27,923 INFO  [STDOUT] Mappings: [/AnotherTestServlet]
02:59:27,923 INFO  [STDOUT] Servlet: jboss.web:j2eeType=Servlet,name=jsp,WebModule=//localhost/de.tutorials.web.test,J2EEApplication=none,J2EEServer=none
02:59:27,923 INFO  [STDOUT] Mappings: [*.jsp, *.jspx]
...

Gruß Tom
 
Hallo,

der Tipp mit JMX ist richtig gut. Man muss nur noch schauen, dass man den String erwischt, den man sucht! :)
Ich habe den Mechanismus schon fuer weitere Workarounds verwendet!

Danke nochmal!

Gruß
meinereiner
 

Neue Beiträge