I'm reading the following documentation
regarding the deployment architecture of embedded Jetty, and I tried to configure a very simple jetty server that loads initially without any WebApps or handlers deployed. The server should hot deploy WARs which are copied to a static directory.
My Code:
public class JettyServerDeploymentManager implements JettyServer {
private Server server;
private DeploymentManager deployer;
private AppProvider appProvider;
public void start() throws Exception {
server = new Server(8090);
// Setup Connector
ServerConnector connector = new ServerConnector(server);
server.setConnectors(new Connector[] {connector});
// Handler Tree location for all webapps
ContextHandlerCollection contexts = new ContextHandlerCollection();
// Deployment Management
deployer = new DeploymentManager();
deployer.setContexts(contexts);
appProvider = new WebAppProvider();
((WebAppProvider) appProvider).setMonitoredDirName("/mytmpdir");
deployer.addAppProvider(appProvider);
server.addBean(deployer);
// Handler Tree
HandlerCollection handlers = new HandlerCollection();
handlers.addHandler(contexts);
handlers.addHandler(new DefaultHandler());
server.setHandler(handlers);
server.start();
server.join();
}
}
This impl should be equivalent to the code provided in the link above (xml configuration).
The server inits without any errors, but when I copy a war file to the scanned directory, nothing happens.
What am I missing? I'm not even sure if the link between my server to the deployment manager is sufficient.
Update:
It seems to be working, at least the scanning part, I've added
static
{
// Make jetty's own logging use java.util.logging
org.eclipse.jetty.util.log.Log.setLog(new JavaUtilLog());
}
And now I see in the logs that the appProvider loads a new war (it fails on NullPtr now)
Apr 08, 2019 2:51:43 PM org.eclipse.jetty.webapp.WebAppContext doStart
WARNING: Failed startup of context o.e.j.w.WebAppContext#19efba8a{/simple1,jar:file:///mytmpdir/simple1.war!/,null}{/mytmpdir/simple1.war}
java.lang.NullPointerException
at org.eclipse.jetty.webapp.MetaInfConfiguration.preConfigure(MetaInfConfiguration.java:77)
at org.eclipse.jetty.webapp.WebAppContext.preConfigure(WebAppContext.java:501)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:539)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.deploy.bindings.StandardStarter.processBinding(StandardStarter.java:41)
at org.eclipse.jetty.deploy.AppLifeCycle.runBindings(AppLifeCycle.java:188)
at org.eclipse.jetty.deploy.DeploymentManager.requestAppGoal(DeploymentManager.java:499)
at org.eclipse.jetty.deploy.DeploymentManager.addApp(DeploymentManager.java:147)
at org.eclipse.jetty.deploy.providers.ScanningAppProvider.fileAdded(ScanningAppProvider.java:180)
at org.eclipse.jetty.deploy.providers.WebAppProvider.fileAdded(WebAppProvider.java:452)
at org.eclipse.jetty.deploy.providers.ScanningAppProvider$1.fileAdded(ScanningAppProvider.java:64)
at org.eclipse.jetty.util.Scanner.reportAddition(Scanner.java:610)
at org.eclipse.jetty.util.Scanner.reportDifferences(Scanner.java:529)
at org.eclipse.jetty.util.Scanner.scan(Scanner.java:392)
at org.eclipse.jetty.util.Scanner$1.run(Scanner.java:329)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Working solution:
public class JettyServerDeploymentManager implements JettyServer {
private static final Logger log = Logger.getLogger(JettyServerDeploymentManager.class.getName());
private Server server;
private DeploymentManager deployer;
private AppProvider appProvider;
static
{
// Make jetty's own logging use java.util.logging
org.eclipse.jetty.util.log.Log.setLog(new JavaUtilLog());
}
public void start() throws Exception {
server = new Server(8090);
// Setup Connector
ServerConnector connector = new ServerConnector(server);
server.setConnectors(new Connector[] {connector});
// Handler Tree location for all webapps
ContextHandlerCollection contexts = new ContextHandlerCollection();
// Handler Tree
HandlerCollection handlers = new HandlerCollection();
handlers.addHandler(contexts);
handlers.addHandler(new DefaultHandler());
server.setHandler(handlers);
// Deployment Manager
DeploymentManager deploymentManager = new DeploymentManager();
deploymentManager.setContexts(contexts);
// App provider
WebAppProvider appProvider = new WebAppProvider();
appProvider.setExtractWars(true); // required for a proper deployment of inner jars
appProvider.setMonitoredDirName("/mytmpdir");
appProvider.setScanInterval(2);
deploymentManager.addAppProvider(appProvider);
server.addBean(deploymentManager);
log.info("starting server");
server.start();
server.join();
}
private static URL findWebAppPath() {
ClassLoader classLoader = SparkApp.class.getClassLoader();
return classLoader.getResource("");
}
Related
Is it possible to configure the ErrorPageErrorHandler in way that it redirects to a static Page if no content/service is found?
Here is my Code:
server = new Server(port);
Resource webRoot = Resource.newResource(webContent);
if (!webRoot.exists()) {
logger.warn("Unable to find root resource:" + webRoot.getName());
} else {
logger.info("Root resource is " + webRoot.getName());
}
ResourceHandler res = new ResourceHandler();
res.setBaseResource(webRoot);
res.setDirAllowed(false);
//servlet handler
ServletContextHandler servletCtx = new ServletContextHandler(ServletContextHandler.SESSIONS);
servletCtx.setContextPath("/service");
servletCtx.addServlet(new ServletHolder("sample", new MyServletSample()), "/sample");
ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler();
errorHandler.addErrorPage(404, "index.html");
servletCtx.setErrorHandler(errorHandler);
// static file handler
ContextHandler staticCtx = new ContextHandler("/");
staticCtx.setBaseResource(webRoot);
staticCtx.setHandler(res);
// add handlers
HandlerList handlerList = new HandlerList();
handlerList.addHandler(servletCtx);
handlerList.addHandler(staticCtx);
// add handerList to server
server.setHandler(handlerList);
This code show me index.html on localhost:8080 and I can access the sample service http://localhost:8080/service/sample. However, I want to show a static error page (i.e. documentation) to show up if an error like "404 Not Found" occured.
With this code, the Error handler logs:
"WARN o.e.j.server.handler.ErrorHandler - No error page found
index.html"
. What is correct way/syntax to define the URI?
Thanks in advance!
This was answered before at https://stackoverflow.com/a/32383973/775715
Don't mix ResourceHandler and ServletContextHandler unless you REALLY know what you are doing, and fully understand the nature of javax.servlet.ServletContext and all of the rules it brings to the table.
See also:
What is difference between ServletContextHandler.setResourceBase and ResourceHandler.setResourceBase when using Jetty embedded container?
Serving static files from alternate path in embedded Jetty
Here's an example of your setup working with NO ResourceHandler, 1 ServletContextHandler, and a DefaultServlet providing the static file serving.
// servlet handler
ServletContextHandler servletCtx = new ServletContextHandler(ServletContextHandler.SESSIONS);
servletCtx.setContextPath("/");
servletCtx.setBaseResource(webRoot); // what static content to serve
servletCtx.setWelcomeFiles(new String[] { "index.html" });
servletCtx.addServlet(new ServletHolder("sample", new MyServletSample()), "/service/sample");
ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler();
errorHandler.addErrorPage(404, "/index.html");
servletCtx.setErrorHandler(errorHandler);
// static file serving, and context based error handling
ServletHolder defaultServ = new ServletHolder("default", DefaultServlet.class);
defaultServ.setInitParameter("dirAllowed","false");
servletCtx.addServlet(defaultServ,"/");
// add handlers
HandlerList handlerList = new HandlerList();
handlerList.addHandler(servletCtx);
handlerList.addHandler(new DefaultHandler()); // non-context error handling
I have (jetty) java web start standalone code something like this. I need to add SSL Certificate for the same.
org.mortbay.util.Log.instance().add(new TomeLogSink(NAME));
server = new HttpServer();
SocketListener listener = new SocketListener();
listener.setPort(port);
server.addListener(listener);
// context to handle all other request including servlets
HttpContext context = new HttpContext();
context.setContextPath(HttpConstants.HTTP_CONTEXT_PATH);
context.setResourceBase(HttpConstants.HTTP_PROVIDENT_ROOT);
//handler for servlets
servletHandler = new ServletHandler();
addServlet("*.jnlp", JnlpServlet.class);
addServlet("/index.htm", IndexServlet.class);
addServlet("/index.html", IndexServlet.class);
CcAdminServiceImpl cc = (CcAdminServiceImpl) RegistryManager.get(
CcAdminService.REGISTERED_NAME);
cc.createWebContent(this);
//handler for static content
ResourceHandler handler = new ResourceHandler();
handler.setDirAllowed(false);
handler.setAcceptRanges(false);
context.addHandler(servletHandler);
context.addHandler(handler);
context.addHandler(new NotFoundHandler());
//setup and start the server
server.addContext(createStaticContext(
HttpConstants.HTTP_HELP_PATH,
HttpConstants.HTTP_HELP_ROOT));
server.addContext(context);
server.start();
Is it right to start a jetty instance with no context specified and no context handler, then keep adding context to it once the server has started. Although I was able to do this using mutable HandlerCollection and the logs says the Server and the Contexts are started and available, I am not able to access it with the URL. Or should we add at least one root context and contexthandler to the server while starting it?
I did something similar to the example suggested in below link.
Jetty 9 (embedded): Adding handlers during runtime
My jetty version is 9.3.7.v20160115
the addition of handlers to a running server is a common pattern but the documentation is not clear at all (all the examples in the "embedding jetty" tutorial start the server after the configuration.) AFAIK people is following these approaches:
1) using the HandlerCollection(boolean mutableWhenRunning) ctor to add/remove handlers
2) add and start the handlers explicitly
I observed that #2 was not needed in Jetty 9.1.4, but it is on Jetty 9.2.14 and afterward (BTW these version numbers were picked by Maven as Jersey dependencies which is totally unrelated to this issue.) For example:
// after server creation ...
ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
jettyServer.setHandler(contextHandlerCollection);
jettyServer.start();
// ...
ServletContextHandler newSCH= new ServletContextHandler(ServletContextHandler.SESSIONS);
newSCH.setResourceBase(System.getProperty("java.io.tmpdir"));
newSCH.setContextPath("/servlets");
ServletHolder newHolder = new SwServletHolder(servlet);
newSCH.addServlet(newHolder, "/*");
contextHandlerCollection.addHandler(newSCH);
try {
newSCH.start(); // needed from about 9.2
} catch (Exception e) {
logger.info("Exception starting ServletContextHandler for Jetty", e);
}
In order to add a SOAP context this is a code that "used to work" on 9.1.4 (on 9.2.14 it reports 404):
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
import org.eclipse.jetty.http.spi.JettyHttpServerProvider;
import org.eclipse.jetty.http.spi.HttpSpiContextHandler;
import org.eclipse.jetty.http.spi.JettyHttpContext;
import org.eclipse.jetty.http.spi.JettyHttpServer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import com.sun.net.httpserver.HttpContext;
public class JettyJaxWs {
public static void main(String[] args) throws Exception {
Server server = new Server(7777);
ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
server.setHandler(contextHandlerCollection);
server.start();
HttpContext context = buildOrig(server, "/ws");
MyWebService ws = new MyWebService();
Endpoint endpoint = Endpoint.create(ws);
endpoint.publish(context);
// access wsdl on http://localhost:7777/ws/MyWebService?wsdl
}
#WebService
public static class MyWebService {
public String hello(String s) {
return "hi " + s;
}
}
public static HttpContext buildOrig(Server server, String contextString) throws Exception {
JettyHttpServerProvider.setServer(server);
return new JettyHttpServerProvider().createHttpServer(new InetSocketAddress(7777), 5).createContext(contextString);
}
Later, I had to do this for the last method (not sure if there is a better way):
public static HttpContext buildNew(Server server, String contextString) {
JettyHttpServer jettyHttpServer = new JettyHttpServer(server, true);
JettyHttpContext ctx = (JettyHttpContext) jettyHttpServer.createContext(contextString);
try {
Method method = JettyHttpContext.class.getDeclaredMethod("getJettyContextHandler");
method.setAccessible(true);
HttpSpiContextHandler contextHandler = (HttpSpiContextHandler) method.invoke(ctx);
contextHandler.start();
} catch (Exception e) {
e.printStackTrace();
}
return ctx;
}
I am developing a multi-module spring boot project. My project structure look like
myProject(parent)
front-end
src/main/resources
frontend
index.html
rest
src/main/java
com.example
MyWebApp.java
com.example.config
WebAppConfig.java
I am trying to configure jetty by injecting JettyServerCustomizer as bean in WebAppConfig as following
#Bean
public JettyServerCustomizer customizeJettyServer()
{
return new JettyServerCustomizer()
{
#Override
public void customize(final Server server)
{
ContextHandler frontEndContext = new ContextHandler();
frontEndContext.setContextPath(""); //what should be here
frontEndContext.setResourceBase("");//what should be here
ResourceHandler frontEndResourceHandler = new ResourceHandler();
frontEndResourceHandler.setWelcomeFiles(new String[] { "index.html" });
frontEndContext.setHandler(frontEndResourceHandler);
ContextHandlerCollection contexts = new ContextHandlerCollection();
contexts.setHandlers(new Handler[] { frontEndContext});
server.setHandler(contexts);
}
};
}
What value to set to contextPath and ResourceBase so that I could run my index.html which is in front-end module? How the url will looks like?
Thank you :)
Spring Boot can serve static content for you. Instead of trying to configure Jetty, place your static content beneath src/main/resources/static and they'll be loaded straight from the classpath.
I am developing a Web Service solution that is hosted inside a JBoss 4.2.3 sever (as the following) and my code connect to Remote JMS queue hat is hosted on another server(192.168.35.25)
public static Context getInitialContext () throws JMSException,NamingException
{
Properties prop = new Properties();
prop.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
prop.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
prop.setProperty("java.naming.provider.url", "192.168.35.20:1099");
Context context = new InitialContext(prop);
return context;
}
public String SendMessages(String msg) throws ServletException, IOException, URISyntaxException {
String body="";
try
{
Context init =ClsSat.getInitialContext();
javax.jms.Queue destination = (javax.jms.Queue) init.lookup("Queue/RemoteQueue");
ConnectionFactory connectionFactory = (ConnectionFactory) init.lookup("ConnectionFactory");
Connection connection = connectionFactory.createConnection("un","pwd");//
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
;
MessageProducer producer = session.createProducer(destination);
TextMessage message = session.createTextMessage();
message.setText(msg);
connection.start();
producer.send(message);
body = message.getText();
session.close();
connection.close();
}
catch (Exception e)
{
return(e.toString());
}
return body ;
}
But I got an error ... RemoteQueue not bound
so any one have an idea or help about connect to remote queus throw web service
or any documents about connect to Remote queue on remote machine from web service hosted on local machine
Can it be because of the wrong IP address in your getInitialContext(), please check if not you can provide some more detail.