Jetty servlet url and port - java

What is the method call to figure out what is the url and port a jetty servlet is running on? So that I can just print it on the screen, and use it in the client to connect:
url = new URL("trying to figure this out");
I am running both the client and the server locally, in eclipse, this is a school project.
Relevant code:
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
public class ServerMain {
public static void main(String[] args){
Server server = new Server();
ServletContextHandler context =
new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("Servlet");
context.setResourceBase("etc/docroot");
server.setHandler(context);
context.addServlet(new ServletHolder(new MyServer()), "/game");
DefaultServlet staticFileServlet = new DefaultServlet();
context.addServlet(new ServletHolder(staticFileServlet), "/*");
System.out.println("context: " + context.getContextPath());
//System.out.println("One valid Port = "
+ context.getServer().getConnectors()[0].getPort());
try {
server.start();
server.join();
} catch (Exception e) {
e.printStackTrace();
}
}
}

Since you are doing this embedded you have a couple of options.
Server server = new Server(8080);
This will start the server on port 8080, which is fine if that is what you want but in unit tests you generally want this to be a random port to avoid issues with things like CI's or parallel tests tripping on each other.
Server server = new Server(0);
This will start the connector on a random port, but how to get that port?
server.getConnectors()[0].getLocalPort();
The port is really coming from the connector, and typically you only are setting up one connector here, so this gets you that port.
Now localhost works for testing well, but if you wanted the name of the host that the connector is on you can use this:
server.getConnectors()[0].getHost();
Chain that stuff up and you get how we do most of our unit testing in jetty itself, spinning up the server itself, wiring up whatever handler or webapps we want and then assert behaviors, requests, responses, etc.
We have a number of embedded examples here that you can look at for different ways to wire up jetty inside code, and the jetty.xml format is just a thin layer of xml over java so you can map the startup of jetty easily through the code by reading the xml file with a java hat on. There is an embedded example in here for bootstrapping jetty based on that xml format as well if you want to keep the config there.
http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded
For a good page on embedding jetty, look here: http://www.eclipse.org/jetty/documentation/current/embedding-jetty.html

Most likely the jetty server is running on 8080 as default. If not you can go and check the server.xml file which should tell you what the port configuration is.

I'm not sure what you're asking here but if you had some servlet i.e Hello :
public final class Hello extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
writer.println("URL is " + request.getRequestURL() + " port is " request.getServerPort());
}
}
Additionally if this is not info what you're looking for please see this :
http://docs.oracle.com/javaee/1.4/api/javax/servlet/http/HttpServletRequest.html
http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.6/api/javax/servlet/http/HttpServletRequest.html

Related

deploying web application to a already started jetty

If I start a jetty server from an external jar using java -jar , and then how can I add another java web application to that specific port that has already been started ? for example, this code :
public class Main {
private static Logger logger = Logger.getLogger(Main.class);
public static void main(String[] args) throws Exception {
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
Server jettyServer = new Server(5701);
jettyServer.setHandler(context);
ServletHolder jerseyServlet = context.addServlet(
org.glassfish.jersey.servlet.ServletContainer.class, "/*");
jerseyServlet.setInitOrder(0);
jerseyServlet.setInitParameter(
"jersey.config.server.provider.classnames",
Calculator.class.getCanonicalName());
try {
jettyServer.start();
jettyServer.join();
} catch (Exception e){
logger.error("error during server starting",e);
jettyServer.stop();
jettyServer.destroy();
}
}
}
If I take the try/catch out, Would the application be added to the already existed 5701 jetty server?
your code starts its own Jetty server on port 5701, there's nothing about that code that will add to a different Jetty server.
Lets say you have ServerFoo on port 5701 already started and running in its own JVM.
You now have another Webapp you want to add to that ServerFoo instance.
You will start a new JVM, lets call it DeployerBar, to control/manipulate the ServerFoo instance.
To do this, you need to communicate with that ServerFoo instance and give it everything it needs to start the WebApp itself (all of the classes, the configuration, etc) first.
Then ServerFoo will need a custom ClassLoader to load these new classes and configuration that it just received, giving it the ability to start this new webapp.
If this is kinda what you are looking to do, consider instead modifying ServerFoo to use the Jetty DeploymentManager to monitor a common webapps directory.
Then your deployment process is just putting all of the files (classes/jars/libs/configuration) into this common webapps directory for the ServerFoo DeploymentManager to just pick up and start using.
See LikeJettyXml.java for an example how this works.
DeploymentManager deployer = new DeploymentManager();
DebugListener debug = new DebugListener(System.err,true,true,true);
server.addBean(debug);
deployer.addLifeCycleBinding(new DebugListenerBinding(debug));
deployer.setContexts(contexts);
deployer.setContextAttribute(
"org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$");
WebAppProvider webapp_provider = new WebAppProvider();
webapp_provider.setMonitoredDirName(jetty_base + "/webapps");
webapp_provider.setDefaultsDescriptor(jetty_home + "/etc/webdefault.xml");
webapp_provider.setScanInterval(1);
webapp_provider.setExtractWars(true);
webapp_provider.setConfigurationManager(new PropertiesConfigurationManager());
deployer.addAppProvider(webapp_provider);
server.addBean(deployer);

How to capture socket objects into external constant in Jetty 9 (migrating from Jetty 7)?

I'm migrating a web application with embedded Jetty from 7 to 9.3.2 and as such am in need of updating the code a little. The application itself has a multitude of connectors written for it, for web UI, API endpoint and also for authenticating to the web interface via a smart card. The connector method for achieving that is implemented as follows (for Jetty 7).
private Connector createSmartCardConnector() {
SslContextFactory sslContextFactory = createSslContextFactory(smartCardUiKeyStoreFile);
LOG.info("Using truststore file: " + trustStoreFile);
sslContextFactory.setTrustStore(trustStoreFile);
sslContextFactory.setTrustStorePassword("password");
sslContextFactory.setNeedClientAuth(true);
Connector connector = new SslSocketConnector(sslContextFactory) {
#Override public void accept(int acceptorID) throws IOException, InterruptedException {
Socket socket = _serverSocket.accept();
configure(socket);
SslConnectorEndPoint connection = new SslConnectorEndPoint(socket);
SMART_CARD_SOCKETS.add((SSLSocket) socket);
connection.dispatch();
}
};
As is apparent from the code, the SslSocketConnector.accept() method is overridden and the only part that is added is SMART_CARD_SOCKETS.add((SSLSocket) socket);. SMART_CARD_SOCKETS is a set that is later used for destroying the objects (sockets) being added to it. My question here is how to achieve the same functionality in Jetty 9, the point of which is that when the smart card is removed from the user's computer, the socket would be destroyed when the user attempts to navigate further.
I have tried to override the ServerConnector.accept() method in Jetty 9, however it uses a private method in it, which makes this impossible.
What you want is a custom implementation of HttpConfiguration.Customizer.
Add it to your HttpConfiguration for the ServerConnector you are interested in, and then it will run with each accept.
Example use of SecureRequestCustomizer.java.
// Setup SSL
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("/path/to/keystore");
sslContextFactory.setKeyStorePassword("password");
sslContextFactory.setKeyManagerPassword("password");
// Setup HTTPS Configuration
HttpConfiguration httpsConf = new HttpConfiguration();
httpsConf.setSecurePort(8443);
httpsConf.setSecureScheme("https");
httpsConf.addCustomizer(new SecureRequestCustomizer()); // adds ssl info to request
// Establish the ServerConnector
ServerConnector httpsConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory,"http/1.1"),
new HttpConnectionFactory(httpsConf));
httpsConnector.setPort(httpsPort);
server.addConnector(httpsConnector);

Facing issues while setting JVM properties for JMX remote management

When I export my JMX agent for remote management, and set the following parameters as VM arguments
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.ssl=false
It works fine as my JMX client is able to easily establish connection with the MBean at port 9999.
Now, I want to set these properties at run time via my configuration file.
I tried setting it via System.setProperty("com.sun.management.jmxremote.port","9999"); and other properties similarly but to no avail.
The JMX Agent doesn't get exposed for remote management in this way.
I even tried creating a registry on the port 9999 but still doesn't seem enough.
private void init() {
try {
LocateRegistry.createRegistry(9999);
System.setProperty("com.sun.management.jmxremote", "true");
System.setProperty("com.sun.management.jmxremote.authenticate", "false");
System.setProperty("com.sun.management.jmxremote.port", "9999");
System.setProperty("com.sun.management.jmxremote.ssl", "false");
} catch (RemoteException e) {
e.printStackTrace();
}
}
I just don't understand why setting these properties via VM arguments works and not while setting the same properties programatically as I described above.
This is what works for me. I am assuming you already know how to right SimpleMXBean used in below example.
Reference Oracle JMX Tutorial. (See section Mimicking Out-of-the-Box Management Using the JMX Remote API.)
package sample;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.rmi.registry.LocateRegistry;
import java.util.HashMap;
import java.util.Map;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
public class MBServerTest {
public static void loadJMXAgent(int port, MBeanServer mbs) throws IOException {
LocateRegistry.createRegistry(port);
System.out.println("Initialize the environment map");
Map<String,Object> env = new HashMap<String,Object>();
env.put("com.sun.management.jmxremote.authenticate", "false");
env.put("com.sun.management.jmxremote.ssl", "false");
System.out.println("Create an RMI connector server");
JMXServiceURL url =
new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:"+port+"/jmxrmi");
JMXConnectorServer cs =
JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
// Start the RMI connector server.
//
System.out.println("Start the RMI connector server");
cs.start();
}
public static void main(String[] args) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
loadJMXAgent(1199,mbs);
SimpleStandard cache = new SimpleStandard();
ObjectName name = new ObjectName(
"org.javalobby.tnt.jmx:type=ApplicationCacheMBean");
mbs.registerMBean(cache, name);
imitateActivity(cache);
}
private static void imitateActivity(SimpleStandard cache) {
while (true) {
try {
cache.cacheObject("hello");
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
Setting the system properties from your application is a bit too late. The JMX agent has already been loaded and initialized.
You can use a JMX configuration file to store the properties in one external file. While it does not allow you read the properties from one shared configuration file it enabled you at least externalize the settings into a different user properties file.
Just providing the property probably does not trigger the creation of an RMI connector on the port that you provided. If you want to enable remote monitoring at runtime then I think you also have to create the connector on the MBean server yourself.
Check out the chapter "Mimicking Out-of-the-Box Management" of the Oracle JMX tutorial. In particular this last bit of the sample code, which uses port 3000 for the RMI server. This is where you want to put the port of your choice:
LocateRegistry.createRegistry(3000);
Map<String,Object> env = new HashMap<String,Object>();
env.put("com.sun.management.jmxremote.authenticate", "false");
env.put("com.sun.management.jmxremote.ssl", "false");
// Create an RMI connector server.
//
// specified in the JMXServiceURL the RMIServer stub will be
// registered in the RMI registry running in the local host on
// port 3000 with the name "jmxrmi". This is the same name the
// out-of-the-box management agent uses to register the RMIServer
// stub too.
//
System.out.println("Create an RMI connector server");
JMXServiceURL url =
new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:3000/jmxrmi");
JMXConnectorServer cs =
JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
// Start the RMI connector server.
//
System.out.println("Start the RMI connector server");
cs.start();
Try to set properties in a static block.
static {
System.setProperty("com.sun.management.jmxremote.port", "9999");
System.setProperty("com.sun.management.jmxremote.authenticate", "false");
System.setProperty("com.sun.management.jmxremote.ssl", "false");
}

Using external server restlet framework

I am using the Restlet Framework, but now I want to change to a proper server instead of using localhost.
I have already added my php files (they access the java files using the rest_server URL) to the server's folder and my java files as well, but I am not sure how to change the code so it identifies where the new location of the files is.
Here is the code from IdentiscopeServer (constructor empty):
public static void main(String[] args) throws Exception {
//setsup our security manager
if (System.getSecurityManager() == null){
System.setSecurityManager(new SecurityManager());
}
identiscopeServerApp = new IdentiscopeServerApplication();
IdentiscopeServer server = new IdentiscopeServer();
server.getServers().add(Protocol.HTTP,8888);
server.getDefaultHost().attach("", identiscopeServerApp);
server.start();
}
I guess that the correct line to change is the one with "Protocol.HTTP, 8888". If the address of my new server is http://devweb2013.co.uk/research/Identiscope, how exactly do I set this up? Is there anything else necessary for it to work apart from just moving the files to a folder in the server?
The IdensticopeServerApplication is the following:
public class IdentiscopeServerApplication extends Application {
public IdentiscopeServerApplication() {
}
public Restlet createInboundRoot() {
Router router = new Router(getContext());
//attaches the /tweet path to the TweetRest class
router.attach("/collectionPublic", CollectionPublicREST.class);
router.attach("/collectionPrivate", CollectionPrivateREST.class);
router.attach("/analysis", AnalysisREST.class);
return router;
}
}
Thank you in advance, it is my first time using this Framework.
If I understand you correctly, you just want to run your main() method as the server, correct? In this case, the code for main() needs to be in a location that -- when running -- can provide the service at http://devweb2013.co.uk/research/Identiscope. Since you haven't stated what kind of server you are putting the code, I can't say where the best place to put the code would be. I assume you have superuser privileges on your deployment server, since the URL you provided implies port 80 will be serving your Identiscope web service (port 80 is a privileged port on most OS's). So as an answer, I can only provide general information.
On your deployment server, port 80 must be free (i.e. nothing else should be acting as a web server on port 80 on that machine) and the IdentiscopeApplication must be running on port 80. To do that, you need only change the line:
server.getServers().add(Protocol.HTTP,8888);
to:
server.getServers().add(Protocol.HTTP, 80);
then run the application as a user that is allowed to start servers on port 80 (preferably NOT the superuser). If you haven't already, you will need to get Java running on your deployment server and make sure all Restlet libraries are in the classpath where you plan to run your application.
If I understand what you are trying to do, then this should do the trick.

Determine that application is running under application server

Some code may be reused in various environments including Java EE Application server. Sometimes it is nice to know whether the code is running under application server and which application server is it.
I prefer to do it by checking some system property typical for the application server.
For example it may be
jboss.server.name for JBoss
catalina.base for Tomcat
Does somebody know appropriate property name for other servers?
Weblogic, Websphere, Oracle IAS, others?
It is very easy to check if you have the specific application server installed. Just add line
System.getProperties() to any JSP, Servlet, EJB and print the result.
I can do it myself but it will take a lot of time to install server and make it working.
I have read this discussion: How to determine type of Application Server an application is running on?
But I prefer to use system property. It is easier and absolutely portable solution. The code does not depend on any other API like Servlet, EJBContext or JMX.
JBoss AS sets a lot of diffrent system properties:
jboss.home.dir
jboss.server.name
You can check other properties using for example VisualVM or other tools.
I don't know other servers but I think you can find some kind of properties for each of them.
This is not a 'standard' way but what I did was to try to load a Class of the AppServer.
For WAS:
try{
Class cl = Thread.getContextClassLoader().loadClass("com.ibm.websphere.runtime.ServerName");
// found
}
// not Found
catch(Throwable)
{
}
// For Tomcat: "org.apache.catalina.xxx"
Etc.
Let me know what you think
//for Tomcat
try {
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("Catalina", "type", "Server");
StandardServer server = (StandardServer) mBeanServer.getAttribute(name,"managedResource");
if (server != null) {
//its a TOMCAT application server
}
} catch (Exception e) {
//its not a TOMCAT Application server
}
//for wildfly
try {
ObjectName http = new ObjectName("jboss.as:socket-binding-group=standard-sockets,socket- binding=http");
String jbossHttpAddress = (String) mBeanServer.getAttribute(http, "boundAddress");
int jbossHttpPort = (Integer) mBeanServer.getAttribute(http, "boundPort");
String url = jbossHttpAddress + ":" + jbossHttpPort;
if(jbossHttpAddress != null){
//its a JBOSS/WILDFLY Application server
}
} catch (Exception e) {
//its not a JBOSS/WILDFLY Application server
}

Categories

Resources