Naming Tomcat worker threads - java

Is there a simple way to change the default name that Tomcat gives its worker threads? Ideally, I'd like all the threads associated with a certain web application to have it in their name, perhaps as a prefix. For example, if I deploy app1.war and app2.war, I'd like all the threads for app1 to have app1 in their name.

From a forum, reposted here with a bit better formatting; a simple filter, that renames each thread to the request URI, in this example:
public class ThreadNameFilter implements javax.servlet.Filter {
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain fc) throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest)req;
final Thread curThr = Thread.currentThread();
final String oldName = curThr.getName();
// change the name of the current thread to something related
// to the application (e.g. URI)
try {
curThr.setName(httpReq.getRequestURI());
fc.doFilter(req, resp);
} finally {
curThr.setName(oldName);
}
}
}

Threads are only temporarily "associated" with a particular webapp.
I can't imagine why this would be something useful at all:
Logging should include context information (e.g. what component is logging)
Profiling can easily reveal what code is being executed (and thus reveal the webapp that is "running")
Exceptions include full stack traces and can reveal what code was being executed (and thus reveal the webapp that was "running")
Long-running threads can be inspected via a thread-dump (and thus reveal the webapp that is "running" in the long-running request)

Related

capturing relevant user requests using filter/interceptors

I am capturing URLs requested for my website. I need to see what all pages were requested from my website.
To achieve this I created a basic filter, and started logging page requests from there.
Now, this filter catches all the requests specific to a page.
For e.g. abc.com/page1, abc.com/resources/myjs.js, etc.
My problem is that for each page request, subsequent resources(js,css) are requested too. I want to capture only the relevant requests.
Right now, I check for patterns like /resources to ignore such requests, but I am looking for a more clean approach.
Also, will interceptors be more useful here?
I have seen filter patterns as well. But those are not useful, since I would have to create patterns for my filter.
If you want to capture the urls accessed from your website, you can configure spring boot to generate access logs in following way until you don't want more advance information:
server.tomcat.accesslog.directory=/logs/ #absolute directory path for log files\
server.tomcat.accesslog.enabled=false #Enable access log.
server.tomcat.accesslog.pattern=any_pattern # log string format pattern for access logs.
To perform any operation based on any request pattern, you can go ahead with filters.
I'm using filters for such requirements in following way:
public class CustomFilter extends OncePerRequestFilter{
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String url = request.getRequestURI();
if (url.startsWith("/resources/")) {
//your business logic
}
filterChain.doFilter(request,response);
}
}

How to abort Startup procedure on init-Exceptions

I have a WebApplication on Websphere 8.5.5.8, one (more or less empty) EAR Project which contains my WAR Project.
In my main Servlet, which is loaded on startup, i do some checks, if everything is alright.
If its not, I'm throwing a javax.servlet.ServletException.
My expectation is, that Websphere would recognize that there is a Problem and abort the startup of my application so its not usable at all.
What actually happens is, Websphere just logs that Exception away with only Waring level, the Exception is even in another File, not in the Log itself:
[06.04.16 07:42:27:229 CEST] 0000004c FfdcProvider W com.ibm.ws.ffdc.impl.FfdcProvider logIncident FFDC1003I: FFDC-Vorfall an C:\IBM\WAS8.5\profiles\AppSrv01\logs\ffdc\server1_bb44715_16.04.06_07.42.27.2056702894000999712166.txt com.ibm.ws.webcontainer.servlet.ServletInstance.init 259 erstellt.
Then my Application is started anyways so its available to use with a Browser. People of course then start using it and recognize later, that that there is a Problem. After digging in Log files, it comes out that the startup failed.
Question:
What can i do to make Websphere abort the Startup Process?
Is there maybe a Special kind of Exception i could throw?
I tried
javax.servlet.ServletException
javax.servlet.UnavailableException
java.lang.Error
I found this in the IBM Forums, which indicates, that my expected behavior would violate the JEE Spec, which wouldn't make much sense for me.
I tried a javax.servlet.ServletContextListener as mentioned here, one Plus is, that i'll get a error Message in the log, but the Application still starts.
As mentioned here I tried the Startup Beans. The solution posted there is not working for me, those proprietary startup beans are not allowed in a WAR, and they're are also Deprecated. I only have a EAR Project, since Websphere/RAD is forcing me to use one in my local environment. On Test/Production Systems, only the WAR is used.
If i use the startup beans defined by EJB 3.1:
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
#Singleton
#Startup
public class MyStartupBean {
public boolean start() {
System.out.println("MyStartupBean.start()");
return false;
}
public void stop(){
System.out.println("MyStartupBean.stop()");
}
#PostConstruct
public void postConstruct() {
System.out.println("MyStartupBean.postConstruct()");
}
}
The start() method doesn't get called, i only see the postConstruct() message in my log. Throwing an Exception in postConstruct() wont abort the startup process.
So far, i only came up with an Workaround (inspired by the comment of Jason Faust in https://stackoverflow.com/a/1337927/5072526):
Have a static flag, and if the initialization has completed correctly, set it to true.
Use a Filter to check that flag and output an Error if its false, so at least the Application dosen't seem usable when the Startup failed:
public class HealthCheckFilter implements Filter{
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if(AppBridge.isStartupFinished()) {
chain.doFilter(request, response);
}else {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setCharacterEncoding(AppConstants.ENCODING);
httpResponse.setContentType("text/plain");
httpResponse.setStatus(500);
PrintWriter out = httpResponse.getWriter();
out.write("Startup failed");
}
}
/* Methods init(FilterConfig filterConfig) and destroy() ommitted*/
}

Tomcat concurrency

I want to use servlet concurrently.
Of course, There is lots of questions related with this subject, but my servlet still works in sequential.
I'm using servlet with Tomcat8, which uses Jena triplestore (with Apache Jena Lib)
My servlet is called within ajax from html, and return data with response.getWriter().write() method.
Each browser is blocked while servlet is running, but it would not matter with concurrent work of servlet I think (because it is each browser's work)
I attach here my server.xml setting:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="300"
acceptCount="200"
minSpareThreads="100"
/>
and doGet method:
#Override
public void init(ServletConfig conf) throws ServletException {
System.out.println("Servlet Run");
}
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String data = request.getParameter("data");
String[] spdata = data.split("\\|");
String sen = spdata[0];
String name = spdata[1];
String id = spdata[2];
System.out.println(sen + ' ' + name + ' ' + id);
int user = id.hashCode();
System.out.println("Load Init");
DialogSystemForTomcat d = new DialogSystemForTomcat(user);
System.out.println("After Init");
System.out.println("Sentence: "+sen);
String rtn = d.runJob(name, sen);
response.getWriter().write(rtn);
System.out.println("Return: "+rtn);
}
As you can see, I call another Java class within doGet() method which really processes my input.
(real process is done within d.runjob() method)
It is working sequentially for all inputs now, but I want to work in concurrent for all inputs.
What should I change? Please help.
=========================================
After...
I worked to make process as faster as possible.
But I could not make it concurrent.
Each browser is blocked while servlet is running, but it would not matter with concurrent work of servlet I think (because it is each browser's work)
You are mistaken. Servlets are concurrent, except for the obsolete SingleThreadModel which you aren't using, and unless they contain synchronized methods or blocks, which this one doesn't, or semaphores, ditto. Ergo this code is concurrent, unless the processing in the unnamed class is synchronized or uses a semaphore of some kind.
NB You have an error in the init() method. It must call super.init(conf). See the Javadoc.

Is there only one servlet object per tomcat server?

I did a simple test, and executed my test servlet below from different browsers and command line tools. Regardless where I execute it, it displays the same "hohoho time". I am absolutly fine with this, I just want to know two things:
a) if I can rely on this on different versions of tomcat (today I use version 7.54)
b) does this mean a servlet is never executed parallel in different threads (i.e. two users are requesting the very same servlet at the very same time)
#WebServlet(name="test servlet 2", urlPatterns={"/test2"}, loadOnStartup=1)
public class Test2 extends HttpServlet {
private String test = "baaa .. :-(";
#Override
public void init(ServletConfig config) throws ServletException {
DEBUG("Server starts");
this.test = "hohoho " + System.currentTimeMillis();
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletOutputStream out = resp.getOutputStream();
out.write(test.getBytes());
out.flush();
out.close();
}
}
Indeed servlet container creates only one instance of each servlet. This helps you to hold state in servlet member variables. This however does not mean that servlet container cannot use the same servlet instance to process serveral requests simultaneously. This is what servlet contains (including Tomcat) does. Therefore your servlet must be thread safe. Please refer to this article for details: http://tutorials.jenkov.com/java-servlets/servlet-concurrency.html
I have below view on your question.
a) Yes,atleast from tomcat 7 onwards.For tomcat 6(annotation support),you will have to check the specs.
b) Regarding execution in parallel thread,servlet not threadsafe by default,to ensure thread safety,Servlet service() method should not access any member variables, unless these member variables are thread safe themselves.
For more on thread safety : Servlet Thread Safety
There is only one instance of each HttpServlet and its init() method is only called once when the HttpServlet is constructed. However the doGet() is called in a different thread for each request and can happen in parallel.

Vanity/Fancy/Rewrite URL implementation that does not suck

I have got a website, with really badly implemented Vanity URL module and really high loads at certain periods of time. Due to some bugs in the url module, the system needs to be restarted every so often. So, I want to rewrite a bloody module to make it nice and less buggy...
Is there are a good pattern to implementing Vanity URL system ?
What is the best approach when dealing with Vanity URL's for high performance ?
What is the best library to look at the sources ?
Cheers.
Ako
I'm not sure about the specific implementation details of your application, but as a general sketch I would write a Filter mapped to the space of URL of interest (perhaps /*).
Such Filter would check if the URL is a fancy one, and in that case would forward the request to the appropiate resource (either a URL dispatcher or a named one). You will need to save the filterConfig.getServletContext() passed in init(FilterConfig) in order to create the request dispatchers. If the URL is not fancy, the filter would invoke chain.doFilter(req, resp), then serving a non-mapped resource.
public class ExceptionFilter implements Filter {
private ServletContext servletContext;
public void destroy() {}
public void doFilter(ServletRequest req,
ServletResponse resp,
FilterChain chain)
throws IOException, ServletException {
String mapping = getMappingFor((HttpServletRequest)req);
if(mapping!=null) servletContext.getRequestDispatcher(mapping).forward(req,resp);
else chain.doFilter(req, resp);
}
public void init(FilterConfig filterConfig) throws ServletException {
this.servletContext = filterConfig.getServletContext();
}
private String getMappingFor(HttpServletRequest req) {...}
How getMappingFor is implemented, depends on the application, but it would probably open a connection to a database and ask whether URL /foo/bar is mapped, returning the mapped URL or nullif there is no mapping. If the mappings are known not to change, you may cache those mappings already retrieved.
You may go with more detailed implementations, such as setting some request attributes depending on the given URL or information from the database, and then forwarding the request to some servlet that knows what to do.

Categories

Resources