Getting server name in ContextLoaderListener - java

My listener is filling Cache (Terracota) and if something goes wrong at application start, ExceptionInInitializerError is thrown. I would like to get server name (like on HttpServletRequest - getServerName()) to know where this happened.
How can I come to this information??
import javax.servlet.ServletContextEvent;
import net.f.core.service.util.CacheUtil;
import org.apache.log4j.Logger;
import org.springframework.web.context.ContextLoaderListener;
/**
* Application Lifecycle Listener implementation class OnContextLoadListener
*
*/
public class OnContextLoadListener extends ContextLoaderListener {
private static final Logger log = Logger
.getLogger(OnContextLoadListener.class);
#Override
public void contextDestroyed(
#SuppressWarnings("unused") ServletContextEvent sce) {
// nothing here
}
#Override
public void contextInitialized(
#SuppressWarnings("unused") ServletContextEvent sce) {
try {
CacheUtil.getInstance();
} catch (ExceptionInInitializerError e) {
log.error("Problem with application start!", e);
// notify me
}
}

The server hostname is part of the request, as it depends on what URL the client used to reach your host.
If you are interested in the local hostname, you can try:
String hostname = InetAddress.getLocalHost().getHostName();

HttpServletRequest.getServerName():
Returns the host name of the server to
which the request was sent.
Its not a property of the server itself, it's a property of the request. It makes no sense outside of the context of the ContextLoaderListener.
What information are you actually looking for?

Simply:
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
....
ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest req = sra.getRequest();
String serverName = req.getServerName();

If you're just trying to determine if you're on localhost:
boolean isLocalHost = "localhost/127.0.0.1".equals(InetAddress.getLoopbackAddress().toString());

Related

Using proxy for specific HTTPS request in java

I have requirement to pass HTTPs calls of some specific URL via proxy and rest direct. I have written my own custom proxy implementation using ProxySelector of java.net. It is working fine for HTTP calls ( I can see in proxy access logs in that case) but in case of HTTPS calls it seems it is not using proxy).Am I missing something here.? Proxy server is configured properly and its access log is updating when some HTTPS calls passed from browser with proxy.
package com.blabla.proxy;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.vuclip.pubsub.logging.PubSubUtil;
import com.vuclip.pubsub.logging.client.GooglePubSubClient;
public class CustomProxySelector extends ProxySelector {
private static final Logger LOGGER = LogManager.getLogger(PubSubUtil.class);
private final ProxySelector def;
private final String PUB_SUB_URL = "pubsub.googleapis.com";
List<Proxy> proxyList = new ArrayList<Proxy>();
private Proxy proxy=null;
public CustomProxySelector(ProxySelector aDefault) {
this.def = aDefault;
}
#Override
public void connectFailed(URI arg0, SocketAddress soc, IOException ex) {
LOGGER.error("Error in connecting to proxcy "+soc +" for pubsub :"+ ex);
}
#Override
public List<Proxy> select(URI uri) {
if ("https".equalsIgnoreCase(uri.getScheme()) && uri.getHost().startsWith(PUB_SUB_URL)
&& GooglePubSubClient.isProxyEnabled()) {
synchronized (this) {
if (proxy == null) {
proxy = new Proxy(Proxy.Type.SOCKS,
new InetSocketAddress(GooglePubSubClient.getProxyHost(), GooglePubSubClient.getProxyPort()));
}
}
proxyList.add(proxy);
LOGGER.debug("ProxyList:" + proxyList);
return proxyList;
}
proxyList = def.select(uri);
LOGGER.debug("Default proxy list : " + proxyList);
return proxyList;
}
}
I changed Proxy.Type.SOCKS to Proxy.Type.HTTP and it worked for me.

Get Request IP in Jersey Request Event Listener

I have the following RequestEventListener in Jersey 2.26:
package com.myapp.webservice;
import org.glassfish.grizzly.http.server.Request;
import org.glassfish.jersey.server.monitoring.RequestEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.core.Context;
public class RequestEventListener implements org.glassfish.jersey.server.monitoring.RequestEventListener {
private static final Logger logger = LoggerFactory.getLogger(RequestEventListener.class);
private final long startTime;
#Context
private javax.inject.Provider<Request> request;
RequestEventListener() {
startTime = System.currentTimeMillis();
}
#Override
public void onEvent(RequestEvent requestEvent) {
switch(requestEvent.getType()) {
case RESOURCE_METHOD_START:
try {
logger.info("HTTPRequest {} /{} {}", requestEvent.getContainerRequest().getMethod(), requestEvent.getContainerRequest().getUriInfo().getPath(), request.get().getRemoteAddr());
} catch (Exception e) {
logger.error("Exception {}", e);
}
break;
case FINISHED:
logger.info("HTTPResponse {} /{} {}", requestEvent.getContainerResponse().getLength(), requestEvent.getContainerRequest().getUriInfo().getPath(), System.currentTimeMillis() - startTime);
break;
}
}
}
I tried to inject the grizzly http Request object, which works like that when i use a RequestFilter instead an EventListener. But i get NullPointerException regarding the request object.
Is it possible to get the request's IP address in that (or any other) way inside an RequestEventListener?
Thanks in advance,
Rob
Probably because you're just instantiating it. You can't expect for it to be injected this way. What you can do is inject it (the Provider<Request> into the ApplicationEventListener and pass it the request listener constructor. Or you could inject the ServiceLocator (InjectionManager for 2.26+) into the ApplicationEventListener and call locator.inject(requestListener). That would explicitly inject the request listener.

Jetty adding web fragment to web context programmatically

I've started to use embedded Jetty Server to start some 3rd-party WAR.
So I use WebAppContext:
Server server = new Server(port);
WebAppContext ctx = new WebAppContext();
ctx.setContextPath("/samplePath");
ctx.setWar(<PATH_TO_WAR>);
server.setHandler(ctx);
server.start();
server.join();
This code works (I've omitted exception handling for the sake of brevity here), however now I would like to add some functionality to the war which I want to leave intact (I mean, don't extract change and compress again).
My functionality should include an integration with some custom SSO solution which should add the following:
A Context Listener
A Filter
Some Context Param Variables definitions that should be read by these Filter and listener
I can't change this SSO solution because its not developed by our team, we rather take it as a thirdparty.
So I thought that adding all this to module with web-fragment would be the best approach.
My question is: what is the best way to make Jetty's web context to be 'aware' of this web fragment? A working code snippet would be great :)
Of course if there is a better alternative than web fragments for this, I'll be glad to know
The version of Jetty I currently use is (from my pom.xml): 9.2.10.v20150310
Thanks a lot in advance!
Here is the way you can specify a web app as well as a filter
import java.io.IOException;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.webapp.WebAppContext;
public class MultipleHandler {
/**
* #param args
*/
public static void main(String[] args) {
Server server = new Server();
ServerConnector connectorA = new ServerConnector(server);
connectorA.setPort(55);
connectorA.setName("connA"); // connector name A
server.addConnector(connectorA);
HandlerCollection contexts = new HandlerCollection();
server.setHandler(contexts);
// A WebApp
WebAppContext appA = new WebAppContext();
appA.setContextPath("/samplePath");
appA.setWar("<warFilePath>");
appA.setVirtualHosts(new String[] { "#connA" }); // connector name A
contexts.addHandler(appA);
//Filter handler
ServletHandler handler = new ServletHandler();
handler.addFilterWithMapping(DoWork.class, "/filter",
EnumSet.of(DispatcherType.REQUEST));
contexts.addHandler(handler);
try {
server.start();
server.join();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
public static class DoWork implements Filter {
#Override
public void destroy() {
// TODO Auto-generated method stub
}
#Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
System.out.print("Request filtered");
}
#Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
}

Grizzly and ServletContainerContext

I'm trying to get hold of some injected context (for example Session or HttpServletRequest) in a Servlet I've written, running on Grizzly, but nothing I do seems to work. The whole process seems to stall rather prematurely with the following error:
SEVERE: Missing dependency for field: javax.servlet.http.HttpServletRequest com.test.server.LolCat.hsr
The server is dead simple, it consists of two files, the static entry point (Main.java):
package com.test.server;
import java.io.IOException;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.grizzly.http.server.HttpServer;
import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;
import com.sun.jersey.api.core.ClassNamesResourceConfig;
import com.sun.jersey.api.core.ResourceConfig;
public class Main {
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost/").port(8080).build();
}
public static final URI BASE_URI = getBaseURI();
public static void main(String[] args) throws IOException {
ResourceConfig rc = new ClassNamesResourceConfig(LolCat.class);
HttpServer httpServer = GrizzlyServerFactory.createHttpServer(BASE_URI, rc);
System.in.read();
httpServer.stop();
}
}
and the serlvet (LolCat.java):
package com.test.server;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
#Path(value = "/lol")
public class LolCat {
#Context HttpServletRequest hsr;
#GET
#Path(value="/cat")
public String list() {
return "meow";
}
}
Specifically, it's the #Context-line in the above source file that is the source and solution to all my problems. I need it, and according to everything I've read about Jersey and Servlets it should work, but alas it does not. I've also tried using GrizzlyWebContainerFactory instead of the GrizzlyServerFactory, but to no avail.
For reference, the project is compiled with the following dependencies:
org.glassfish.grizzly:grizzly-framework:jar:2.2.21
org.glassfish.grizzly:grizzly-http:jar:2.2.21
org.glassfish.grizzly:grizzly-http-servlet:jar:2.2.21
org.glassfish.grizzly:grizzly-http-server:jar:2.2.21
com.sun.jersey:jersey-server:jar:1.17
com.sun.jersey:jersey-servlet:jar:1.17
com.sun.jersey:jersey-core:jar:1.17
javax.servlet:javax.servlet-api:jar:2.5.0
com.sun.jersey:jersey-grizzly2:jar:1.17
com.sun.jersey:jersey-grizzly2-servlet:jar:1.17
asm:asm:jar:3.3.1
This Main class works fine for me:
package com.test.server;
import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;
import java.io.IOException;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import com.sun.jersey.api.core.ClassNamesResourceConfig;
import com.sun.jersey.spi.container.servlet.ServletContainer;
import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.Request;
import org.glassfish.grizzly.http.server.Response;
import org.glassfish.grizzly.servlet.ServletRegistration;
import org.glassfish.grizzly.servlet.WebappContext;
public class Main {
private static final String JERSEY_SERVLET_CONTEXT_PATH = "";
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost").port(8080).path("/").build();
}
public static final URI BASE_URI = getBaseURI();
public static void main(String[] args) throws IOException {
// Create HttpServer and register dummy "not found" HttpHandler
HttpServer httpServer = GrizzlyServerFactory.createHttpServer(BASE_URI, new HttpHandler() {
#Override
public void service(Request rqst, Response rspns) throws Exception {
rspns.setStatus(404, "Not found");
rspns.getWriter().write("404: not found");
}
});
// Initialize and register Jersey Servlet
WebappContext context = new WebappContext("WebappContext", JERSEY_SERVLET_CONTEXT_PATH);
ServletRegistration registration = context.addServlet("ServletContainer", ServletContainer.class);
registration.setInitParameter(ServletContainer.RESOURCE_CONFIG_CLASS,
ClassNamesResourceConfig.class.getName());
registration.setInitParameter(ClassNamesResourceConfig.PROPERTY_CLASSNAMES, LolCat.class.getName());
registration.addMapping("/*");
context.deploy(httpServer);
System.in.read();
httpServer.stop();
}
}
Try http://localhost:8080/lol/cat in your browser.
You can change JERSEY_SERVLET_CONTEXT_PATH to update Servlet's context-path.
As per developers explanations - Grizzly is not fully compliant to JAX-RS 2.0 so there will be no official contexts injections/wrapping. See Jersey Bug-1960
Applicable for Jersey + Grizzly version 2.7+
Luckily there is a way to inject Grizzly request/response objects. Kind of tricky but works
Code sample provided in one of Jersey's unit tests. See Jersey container test
So code fragment will be:
import javax.inject.Inject;
import javax.inject.Provider;
public someclass {
#Inject
private Provider<Request> grizzlyRequestProvider;
public void method() {
if (grizzlyRequestProvider != null) {
Request httpRequest = grizzlyRequestProvider.get();
// Extract what you need
}
}
}
Works fine both for filters and service methods
You can also manually register a ResourceContext
HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(getBaseURI());
WebappContext context = new WebappContext("WebappContext", "/api");
ServletRegistration registration = context.addServlet("ServletContainer",
new ServletContainer(config));
registration.addMapping("/*");
context.deploy(httpServer);
Where config is your resource context.
Try something like this :-
public class Main {
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost/").port(8080).build();
}
public static void main(String[] args) throws IOException {
ResourceConfig rc = new ResourceConfig().packages("com.example");//path to you class files
HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc);
System.in.read();
httpServer.stop();
}
}

Jetty 6: How to remove a Servlet?

I need to programmatically add and remove a servlet on a Jetty 6 server.
While it is almost straighforward to add I cannot find an effective way to remove.
For my purposes it is important to add and remove a servlet because it is associated to a dynamic compontent architecture. I need to add a new service when I add a component and I need to remove the service when I remove the component.
To add a servlet I used this pattern:
Server server = new Server(8080);
class MyServlet extends HttpServlet
{
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
resp.getOutputStream().write("Hello World!".getBytes());
}
}
...
public void addServlet(HttpServlet s, String path)
{
Context root = new Context(server,"/",Context.SESSIONS);
root.addServlet(new ServletHolder(new MyServlet()), "/test/*");
root.getServletHandler().
}
public void removeServlet(HttpServlet s, String path)
{
//What I have to put here ? There is no removeServlet like methods in server/Context/ServletHolder
}
Why removing a servlet is not so obvious? Can you explain me the motivations ?
first off I would recommend updating to jetty 7 or 8 if its possible, jetty 6 is quite old at this point and is lacking the last couple years of development that are present in 7 and 8. heck, jetty 9 is being actively worked on now.
second I wouldn't look at this on the servlet level but the handler level, working with the server to add and remove handlers, which can be either static resource type handlers or full fledged servlet context handlers, or even webapp context handlers.
as to why the servlet context handlers do not have remove servlet type operations, its really not a part of the servlet spec to remove active servlets at that level, fits more at the war deploy/undeploy level. feel free to open an issue on it though, I did experiment with adding and removing at servlet context handler level and you can remove them but it seems to be problematic then adding more afterwards, so I suspect removing the context itself and adding a new one would be your best bet at this point.
Here's instructions for doing it on Jetty 7.
Jetty : Dynamically removing the registered servlet
It should be pretty straight forward to port that code to Jetty 6.
This solution seems to be working:
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.ContextHandler;
import org.mortbay.jetty.handler.ContextHandlerCollection;
import org.mortbay.jetty.handler.ResourceHandler;
import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.servlet.ServletHandler;
import org.mortbay.jetty.servlet.ServletHolder;
import org.mortbay.jetty.servlet.ServletMapping;
public class MyServer extends Server
{
ServletHandler sh = new ServletHandler();
public MyServer()
{
super(9090);
setHandler(sh);
test();
}
class MyServlet extends HttpServlet
{
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
resp.getWriter().println("CIAO!");
}
}
void test()
{
MyServlet ms = new MyServlet();
addServlet(ms, "/ciao/*");
//removeServlet(ms);//uncomment this ilne in order to remove the servlet right after the deploy
}
public void addServlet(HttpServlet s, String path)
{
sh.addServletWithMapping(new ServletHolder(s), path);
for (ServletHolder so : sh.getServlets())
try
{
System.out.println((so.getServlet() == s));
} catch (ServletException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void removeServlet(HttpServlet s)
{
try
{
HashSet<String> names = new HashSet<String>();
for (ServletHolder so : sh.getServlets())
if (so.getServlet() == s)
names.add(so.getName());
HashSet<ServletMapping> sms = new HashSet<ServletMapping>();
for (ServletMapping sm : sh.getServletMappings())
{
if (!names.contains(sm.getServletName()))
sms.add(sm);
}
sh.setServletMappings(sms.toArray(new ServletMapping[] {}));
} catch (ServletException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Categories

Resources