Re: TomCat 6 performance issues
Can you run a load test from another computer on the local network? Something like apache AB gives a histogram and you should be able to tell what percentage of your requests is the 5 seconds range. It is best to run it directly to the tomcat private IP that is used inside the local network, to make the path from the load test client to tomcat as short as possible. That depends on your network configuration, which varies among different colos and clouds. If the loaded tomcat does not max the system resources (which can happen if the application depends on an external app, like a relational database or web service) you can even run AB on the same machine and get close enough results, with the benefit of eliminating potential network delays that may be a suspect. Before you run the load test, do a wget or something like that from the client machine to ensure that you are getting the correct response. AB will also give you the size of the response, which you can use to verify that the client actually gets correct responses from tomcat. If you have something fronting tomcat, you can run the load test once to tomcat and again to the fronting application or load balancer. You will get a general idea of latency of the different components. E - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: 2 Apache 1 Tomcat
A note on reverse proxy: request.getRemoteIP() will normally return the IP of the proxy and not the IP of the client. In Tomcat you will probably need to add a valve such as RemoteIPValve (search this list) to fix the IP of the incoming request. Otherwise your log files will show the IP of the proxy on all requests instead of the IP of the client. Proxies add the IP of the caller as an HTTP header. For the log files you can avoid the valve by changing the log pattern to log the HTTP header of the IP instead of the standard log patterns (combined, common etc). In that case you do not need the valve. I still prefer the valve since it fixes the IP for the application code as well as the log, so everything works normal. We use reverse proxy instead of AJP since we put squid in front of tomcat instead of apache. Depending on your requirements, I would suggest looking into squid instead of apache, but expect a learning curve. E - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: [OT] Context Chicken Egg Problem
Another simple way to use tomcat with eclipse is to start tomcat with remote debugging, and attach to it from eclipse. A couple of switches in the tomcat startup script should do it. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: 2 Apache 1 Tomcat
Or use apache as reverse HTTP proxy in front of Tomcat. In that case tomcat is an HTTP server and there is nothing special to do (just configure HTTP connector). You can put as many apache reverse proxies as you need, tomcat configuration is agnostic to the proxies for the most part. This will also give you the option of using other reverse proxies in addition to apache. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Very slow shutdown - 3 mins
You have many threads that are not part of Tomcat, as Chuck mentions. Whatever you start in the webapp you have to close as well. You can close via a shutdown listener (Context listener), or if you use something like Spring which already has built in shutdown hook, implement their shutdown interface or register a callback. When you shutdown a java executor (which can be seen in the thread dump), notice that to be safe you can do a two steps shutdown. Step 1 does a graceful shutdown and waits. When the graceful shutdown times out and the pool has not finishes, step 2, “hard” shutdown to finish quickly. This will give you the benefit of finishing pending tasks and limit the amount of time allowed before you kill the pool. A hard shut down also means that tasks that are still waiting in the pool will not be executed, so use with caution. This also goes for everything that you create that potentially has persistent resource usage, such as connection pools, HttpClient, etc. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Char Encoding text streams on Tomcat 5.5 and Linux
I was not replying to any post by you. I was replying to a post by a fellow named Dan. He states I have been successful using the charset filters on HTTP posts and XML I am not sure I can respond to your comments since it seems that we talk about different topics. In either case, why vent? E On Wed, Dec 2, 2009 at 8:17 AM, Christopher Schultz ch...@christopherschultz.net wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Elli, On 12/2/2009 2:40 AM, Elli Albek wrote: On your Linux box type “locale” + enter. The results should be UTF 8. If not change it. I can have my locale set to whatever I'd like, thank you very much. You can also set it in the file encoding java environment variable as suggested above as extra safety measure. Well, you can check it's value. By default, it's UTF-8 on my system (as mentioned in my post if you read the whole thing). Tomcat’s logic of determining the encoding from the request only applies when Tomcat is parsing text in the request. Tomcat's logic of determining the encoding for the request is mandated by the servlet spec and the HTTP spec. In this case, Tomcat /was/ parsing text in the request: we are talking about POST data, here. Elli, please read the posts before replying. However if you read from the stream directly, using request.getInputStream() you are getting binary data. When you create java.io.Reader from that input stream you need to specify the encoding, or it will default to the file system encoding. Yes. If you look at the source code to Tomcat, you'll see that the encoding used comes from the request headers, or defaults to ISO-8859-1. I'm not going to repeat this again. If you create your own Reader (which you shouldn't be doing), you're on your own. In this case, nobody was creating their own Reader. The fact that tomcat is using ISO-8859-1 to read characters is not relevant if you are reading from the stream directly and use your own Reader to convert to characters. ..which I wasn't doing. Rather than repeatedly complaining about how you haven't read this thread properly, I'm simply going to stop. I am assuming this is a likely cause, since the XML parsing succeeds Okay, I can't help myself: when did we start talking about XML? - -chris -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.10 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAksWkwEACgkQ9CaO5/Lv0PCI1QCgkC9SPmdWkHDPiLmEqE9l3xGm ASIAoLViW6EMWL67yVxBfMEJDXj9utR4 =R438 -END PGP SIGNATURE- - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Char Encoding text streams on Tomcat 5.5 and Linux
Hi, On your Linux box type “locale” + enter. The results should be UTF 8. If not change it. You can also set it in the file encoding java environment variable as suggested above as extra safety measure. Tomcat’s logic of determining the encoding from the request only applies when Tomcat is parsing text in the request. However if you read from the stream directly, using request.getInputStream() you are getting binary data. When you create java.io.Reader from that input stream you need to specify the encoding, or it will default to the file system encoding. In that case the reader is a java API that does not go through the tomcat APIs. This reader has no knowledge of the request data, any encoding specified in it or what tomcat will default to. The fact that tomcat is using ISO-8859-1 to read characters is not relevant if you are reading from the stream directly and use your own Reader to convert to characters. I am assuming this is a likely cause, since the XML parsing succeeds, so I assume the XML parser is getting raw bytes from tomcat rather than characters (using request.getInputStream() as opposed to request.getReader()). In that case the XML parser will resolve the encoding by itself. Ideally when you create your own reader for plain text you can use the character set in the request, however if you do not trust the clients just force UTF-8 for the OS and the tomcat process by specifying the OS locale. You can also force UTF8 encoding when you create the reader in your java code (it is a constructor parameter for the reader), but it is looks easier to just specify it in the OS/tomcat start up without changing the application code. E
Re: Java Out of Heap Issue
I consider old code part of application code :) no age discrimination when it comes to memory leaks. What you describe in your memory graph is a simple memory leak. Generally, I would look in that order: 1a. Old code? Look for improperly closed DB connections. 1. Sessions 2. Application code 3. Other webapps p - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Possible to do async processing?
Hi, The advices given above are good. If you make this job triggered by a servlet, then an attacker can use it to easily bring down your system with excessive load. You also have problems of clean shutdown. The thread pool that you start needs to have blocking shutdown with some context listener, to make sure that all jobs are finished when you undeploy or shut down the server. This is not hard to do, but you should test it by making sure a job finishes when you shut down. Just add a slow job that, and kill the server. Slow job: public void run(){ System.out.println(Starting slow job); try{ Thread.sleep(6); // 1 min }catch(Throwable e){ e.printStachTrace();// possible kill, watch out for this } System.out.println(Finished slow job); } Add this job to the pool, shut down the server, and look at the logs for the messages. You should also see the server hanging until the job is completed. A simpler option would be to write a java class with a main method, and run it from cron. We have a bunch of those. Not dependent on tomcat, no security problems. You can have many tomcats with the same configuration, something that would be more difficult with a scheduler that is part of your app. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Some advice on apache tomcat
You can also look at squid to serve static files and load balance. So squid fronts tomcat and your other apps. Squid can serve your static files as well. All you have to do it make sure your static files return a cache header like max-age, and squid will serve them without going to the origin (tomcat). Squid can also load balance tomcats and route requests for multiple origins based on some rules. We have squid doing virtual hosting of tomcats that run different apps, as well as serving static content and caching dynamic content. The down sides vs apache: 1. Not as many plugins and options 2. The configuration rules are simpler and more widely known/understood in apache 3. Hard to rewrite URLs. Not impossible, but mod rewrite is much much easier to deal with. Actually any manipulation of the request/response is less than trivial on squid. If you go for squid, 2.7 and above. Earlier versions are not as good for reverse proxing. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Java Out of Heap Issue
You can try getting an object dump from a profiler and see which objects are the source of memory starvation. Simple JSPs are very unlikely to cause memory starvation, but you mentioned “application code”, which implies that you have more than simple JSPs. A few things you want to cross off your performance check list, which will not solve your problem, but are generally necessary: 1. JVM -server option, just in case 2. Disable session persistence 3. If you application does not use sessions, disable them for all JSPs (typical place to do it is header JSP include) 4. Force session termination, no long running sessions. 5. Remove all apps that you do not need. Tomcat comes with a few built in apps and those are not trivial to find. Make sure conf/Catalina and all its sub directories contain only apps that you need. Host manager and such should be deleted. Same with war files. What you describe in your memory graph is a simple memory leak. Generally, I would look in that order: 1. Sessions 2. Application code 3. Other webapps 1 and 3 are easy to deal with. If you don’t need sessions make sure they are not created at all. If you do, force session termination after a few minutes in master web.xml or other XML files. Notice that one file can define a value and another can overwrite it, so you have to make sure all are checked. If that does not work, application code is the next candidate. You can start with an object dump with a profiler or a simple code review/step through in a debugger. E - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Regarding 1 Webserver Multiple Web App project
Tomcat by itself as a web server can do that without too much complexity. If you use something in front of it, then that something need to know which domains go to tomcat as well. You don't necessarily need to front tomcat with apache/AJP. You can have tomcat be the web server as well, or front it with any HTTP reverse proxy such as squid. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Memory, handles and threads increasing in Tomcat 5.5
Hi, Without knowing what your application is doing, here is something you should look at: External dependencies. If your application is stable performance wise at steady state for a few thousands of GC cycles, and then jumps in resources out of nowhere, it is very possible that this is due to an external interruption. Possible interruptions: 1. Another process that runs on the machine of the tomcat server. Cron job, log file compression, you name it. Go over the process list and cron to start with. We run performance tests only on very clean machines, bare bones linux with java and tomcat and nothing else. 2. If your app is using an external application, like a relational database, web service, other HTTP server, email system, that system may be the periodic bottleneck. If it has a periodic interruption (like a job that runs on that machine, or just its own behavior under constant load), it may block your threads for a short amount of time, causing the thread count to increase. 3. Something that runs periodically inside your application. Same as above, but not external. This may also be a third party library that you use in your app without directly doing it yourself. 4. Get rid of all webapps that are not the web app that you test. There are a few that come with tomcat by default. Make sure your tomcat runs only the app you are testing. Conf/Catalina and all its subdirectories should contain one xml file at most if you need context files. All your web app directories together should contain one war file/directory combined. 5. If your system actually consists of a few war files, load test each one of them separately to find the trouble maker. When you test one, the others should not be installed on tomcat (IE, delete the war file and its sibling directory). Not installed and not running, NOT INSTALLED. Big difference. Try to do a thread dump while the jump is happening, if you can catch that. If you can get a thread dump while the number of the threads increasing (sounds like difficult timing from what you describe) you will see what the threads are doing at that point, and at least one of thread will be able to give you an insight why they cannot handle the current momentary load. That is quite a coincidence that as we speak I am dong exactly that, load testing tomcat on different EC2 combinations :) E
Re: Tomcat 6 encoding issue
You can try forcing the JVM to start with UTF 8 using a JVM parameter. -Dfile.encoding=UTF-8 Where you put it depends on how you start tomcat, I think JAVA_OPTS will do it. This is quick and may work. You can also try to force the servlet output stream to be in the encoding that you want from your code before you do any writing. If you are writing the text from a servlet, its a function of the response. If you are doing it in JSP, it is a parameter of the JSP page. %...@page pageEncoding=UTF-8% You must define the encoding on the output stream before you start writing. We have a warning in one of our startup classes, so we know about those problems when they happen (in this case its in filter init, can be pretty much anywhere) String defaultCharset = Charset.defaultCharset().name(); if (!defaultCharset.substring(0, 3).equalsIgnoreCase(utf)) { // not UTF! logger.warn(JVM Character encoding is not UTF, it is ' + defaultCharset + '); } - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: [OT] WebappClassLoader and undeploy
Tomcat 5.5 version + log message when executed: /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the License); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.catalina.core; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import javax.imageio.ImageIO; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleListener; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.tomcat.util.res.StringManager; /** * Provide a workaround for known places where the Java Runtime environment can * cause a memory leak or lock files. * p * Memory leaks occur when JRE code uses * the context class loader to load a singleton as this will cause a memory leak * if a web application class loader happens to be the context class loader at * the time. The work-around is to initialise these singletons when Tomcat's * common class loader is the context class loader. * p * Locked usually files occur when a resource inside a JAR is accessed without * first disabling Jar URL connection caching. The workaround is to disable this * caching by default. */ public class JreMemoryLeakPreventionListener implements LifecycleListener { protected static final Log log = LogFactory.getLog(JreMemoryLeakPreventionListener.class); protected static final StringManager sm = StringManager.getManager(Constants.Package); /** * Protect against the memory leak caused when the first call to * codesun.awt.AppContext.getAppContext()/code is triggered by a web * application. Defaults to codetrue/code. */ protected boolean appContextProtection = true; public boolean isAppContextProtection() { return appContextProtection; } public void setAppContextProtection(boolean appContextProtection) { this.appContextProtection = appContextProtection; } /** * Protect against resources being read for JAR files and, as a side-effect, * the JAR file becoming locked. Note this disables caching for all * {...@link URLConnection}s, regardless of type. Defaults to * codetrue/code. */ protected boolean urlCacheProtection = true; public boolean isUrlCacheProtection() { return urlCacheProtection; } public void setUrlCacheProtection(boolean urlCacheProtection) { this.urlCacheProtection = urlCacheProtection; } public void lifecycleEvent(LifecycleEvent event) { // Initialise these classes when Tomcat starts if (Lifecycle.INIT_EVENT.equals(event.getType())) { log.info(Running JreMemoryLeakPreventionListener (appContextProtection= + appContextProtection + , urlCacheProtection= + urlCacheProtection + ')'); /* * Several components end up calling: * sun.awt.AppContext.getAppContext() * * Those libraries / components known to trigger memory leaks due to * eventual calls to getAppContext() are: * - Google Web Toolkit via its use of javax.imageio * - Tomcat via its use of java.beans.Introspector.flushCaches() in * 1.6.0_15 onwards * - others TBD */ // Trigger a call to sun.awt.AppContext.getAppContext(). This will // pin the common class loader in memory but that shouldn't be an // issue. if (appContextProtection) { ImageIO.getCacheDirectory(); } /* * Several components end up opening JarURLConnections without first * disabling caching. This effectively locks the file. Whilst more * noticeable and harder to ignore on Windows, it affects all * operating systems. * * Those libraries/components known to trigger this issue include: * - log4j versions 1.2.15 and earlier * - javax.xml.bind.JAXBContext.newInstance() */ // Set the default URL caching policy to not to cache if (urlCacheProtection) { try { //
Re: [OT] WebappClassLoader and undeploy
Actually Mark can you take a quick look at the class I sent and see if it makes sense. I swapped juli with commons logging (which is in bin) but now I am not sure this is necessary, this library may already be loaded regardless of this filter. E - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 6 encoding issue
Which library are you using to get the external page? java.net? HttpClient? What do you do with the page that you download? It looks from the exception that you are writing it to the servlet IO, is that the case? Are both of your tomcats running on the same JVM version? E On Wed, Nov 11, 2009 at 8:10 PM, pramodpm pramod_me...@satyam.com wrote: We are facing an encoding issue in apache-tomcat-6.0.20. This is working in tomcat 5.5.23. We are trying to make a get request to external site. The page contains some utf-8 characters. When we access the page from the application we are getting the following error. Can you please help us to resolve this issue. Any help is appreciated. WARNING: Handler caused Not an ISO 8859-1 character: 83 java.io.CharConversionException: Not an ISO 8859-1 character: 83 at javax.servlet.ServletOutputStream.print(ServletOutputStream.java:89) at at java.io.OutputStream.write(OutputStream.java:99) -- View this message in context: http://old.nabble.com/Tomcat-6-encoding-issue-tp26313150p26313150.html Sent from the Tomcat - User mailing list archive at Nabble.com. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: [OT] WebappClassLoader and undeploy
Sorry Mark. Well this class loading scheme (context class loader - static variable) sounds little like a bug. Thanks for that startup class. I think it will solve a problem that we have (using imageio). So you just add it as high up as possible in the server.xml hierarchy? E - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: WebappClassLoader and undeploy
Managing class loaders is done in the JVM. Tomcat cannot force the JVM to garbage collect class loaders, in the same way that it cannot force the JVM to garbage collect any object. If the class loader is unreachable, and all other objects that this class loader provided are also unreachable, then the JVM can garbage collect it like any other object. This garbage collection is heavier than simple object reference. I assume the JVM will do it only in major garbage collections and maybe even not in every major one. If your test app is not doing anything, there is no reason for the JVM to actually do something about it since memory is not consumed. If you try to force major garbage collections, eventually it should happen. If you run a load test, which will force tomcat to consume memory, then you will eventually get to a major garbage collection. This can take much longer than what you would think. If the code is simple (like JSP page and hello world type of servlet) it can be optimized by the JVM to consume memory on a local stack based heap (per thread), and not use the JVM main heaps. If you keep a reference to one object that was created from this class loader, then the Class object of this object is reachable, and the class loader is reachable via the Class. Since it is reachable, it cannot be garbage collected. WebappLoader is a class that has the code to manage a webapp lifecycle. It is not a class loader. The JVM to track references to it like any other simple object (String). In addition, it is an internal tomcat object, so it is a lot simpler to keep track of references to it in the tomcat code. It is not visible to the webapps or exposed to user code that can leak it. WebappClassLoader is the opposite: It is a real class loader. Garbage collecting it is not a simple matter. My guess is that: 1. If you constantly load the memory, then eventually it will be garbage collected. 2. If it is not garbage collected in that case, there is a reference leak, something is keeping a reference to either the class loader or to an object that was loaded by from it. Tomcat is releasing references to objects on its side, but the user code can do other things. If the web app contains one servlet and one JSP page, that should be easy to follow. Tomcat keeps references to those objects (both should be servlets), but also releases them when you redeploy. You can verify that the objects are gone. The actual instances should be gone very quickly since they are simple objects. JSP page is turned into a class, you should see it in the memory management tool. Notice that if the web app is reloaded, the new class loader will load the same classes again, so they will have the same class name, but they will have separate Class instances. You will have two objects that have the same class name, but are different class. Other possible reference leaks from the webapp to the outside: Threads that are left running JNDI Sessions Thread local Any library in a class loader above the webapp (in class loaders app, system, common and shared, possibly even in Catalina but less likely) Logging and reflection libraries always star as favorite leakers. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: WebappClassLoader and undeploy
Thomas, what is the issue with javax.imageio? Do they really use context class loader for loading static variables? - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: [OT] ConnectionPool question
Chris, as long as we are having fun its all good. I think this question is something many developers ask. I have seen it here and in other forums. You are correct, everything is wrapped. The connection wrapper spawns statment wrappers which spawn result set wrappers, and everything is tracked in parent child relationships. E On Fri, Nov 6, 2009 at 5:54 PM, Christopher Schultz ch...@christopherschultz.net wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Elli, Okay, I think we've hijacked Josh's thread enough to at least mark it as off topic. :) On 11/5/2009 10:37 PM, Elli Albek wrote: Christopher Schultz wrote: Pooled connections are almost certainly not behaving this way. This has been discussed at least twice in the last week or two, and, I believe, already once in this thread. This is certainly not the case for my DBCP library (1.2.2). I just stepped through the source code: Calling connection.close() is closing result sets and statements. I'm not sure how calling Connection.close (where the Connection object is one from DBCP) would possibly be able to close ResultSet and Statement objects created by the underlying connection. Unless, I suppose, they decided to wrap /everything/ and register all the ResultSet and Statement objects handed-out by the underlying Connection for the purposes of (possibly) closing them later. I should really read the source :) Below is the DBCP code that keeps track of open statements/result sets and closes them when the connection is closed (BDCP 1.2.2). Yup: it looks like they do wrap/register everything and then close it for you. It's nice that they followed the spec, here :) - -chris - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: SEVERE: All threads (700) are currently busy, waiting. Increase maxThreads (700) or check the servlet status
As Charles suggested, you need a thread dump. There is too much complexity in your setup to be able to find your problem without actually inspecting the machine, but a thread dump can take you right to the source of the problem in a matter of minutes. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: ConnectionPool question
Hi, Elli, On 11/4/2009 7:01 PM, Elli Albek wrote: I also remember that closing a connection closes statements and result sets, but it has been a while since I read the source. Pooled connections are almost certainly not behaving this way. This has been discussed at least twice in the last week or two, and, I believe, already once in this thread. - -chris This is certainly not the case for my DBCP library (1.2.2). I just stepped through the source code: Calling connection.close() is closing result sets and statements. In addition I commented the code that closes statements and result sets in our framework to create a leak, and DBCP closed everything. Relevant DBCP Code snippets below. Josh: You are correct, wrapping connections, statements and datasources is not a good idea. It is complicated code and can lead to many problems. Fortunately for you, you don’t have to do that. You can recklessly leave statements and result sets open, and as long as you call connectiohn.close() at the end DBCP will do all the work for you. You can verify this by downloading the source code, and putting a break point just before you call close. I am telling you this based on experience. We do wrap everything for logging purpose (data source, connection, statement). Doing it was far from trivial, even using the DBCP ready-to-use wrapper classes (DelegatingConnection, DelagatingStatement…). Of course is it good to follow best practices and close things as soon as possible in finally blocks. But in your case, it may just be an unnecessary intermediary step that you can skip. Maybe you can start with a brute force filter and rely on the good fellows that wrote DBCP to clean up the mess. Then go to a better solution, where you use a framework that does most of this work for you. There are too many java database frameworks to list, some of them are heavy, some are minimal right above the JDBC layer, and still provide automatic closing of resources. Below is the DBCP code that keeps track of open statements/result sets and closes them when the connection is closed (BDCP 1.2.2). PollableConnectionFactory: public void passivateObject(Object obj) throws Exception { ... if(obj instanceof DelegatingConnection) { ((DelegatingConnection)obj).passivate(); } } DelegatingConnection (called via subclass PollableConnection): protected void passivate() throws SQLException { try { // The JDBC spec requires that a Connection close any open // Statement's when it is closed. List statements = getTrace(); if( statements != null) { Statement[] set = new Statement[statements.size()]; statements.toArray(set); for (int i = 0; i set.length; i++) { set[i].close(); } clearTrace(); } setLastUsed(0); if(_conn instanceof DelegatingConnection) { ((DelegatingConnection)_conn).passivate(); } } finally { _closed = true; } } Delegating statement: public void close() throws SQLException { try { try { if (_conn != null) { _conn.removeTrace(this); _conn = null; } // The JDBC spec requires that a statment close any open // ResultSet's when it is closed. // FIXME The PreparedStatement we're wrapping should handle this for us. // See bug 17301 for what could happen when ResultSets are closed twice. List resultSets = getTrace(); if( resultSets != null) { ResultSet[] set = (ResultSet[]) resultSets.toArray(new ResultSet[resultSets.size()]); for (int i = 0; i set.length; i++) { set[i].close(); } clearTrace(); } _stmt.close(); } catch (SQLException e) { handleException(e); } } finally { _closed = true; } } - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: ConnectionPool question
As far as I remember, abandoned is a connection that was not closed. So if you call recycle on a connection it will not generate abandoned message. The messages that you see are from connections that you do not close. I also remember that closing a connection closes statements and result sets, but it has been a while since I read the source. Give the filter above a shot. It would takes maybe an hour to get running and can solve all your problems in one go. You may experience a major boost to your system performance even comparing to closing every connection (because you will be using a single connection per request as opposed to multiple open/close). E On Wed, Nov 4, 2009 at 11:43 AM, Christopher Schultz ch...@christopherschultz.net wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Josh, On 11/4/2009 12:11 PM, Josh Gooding wrote: type=javax.sql.DataSource [snip] res-typejavax.sql.DataSource/res-type I believe it is these types that must match, and they do. Don't change a thing. - -chris -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.10 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkrx2VUACgkQ9CaO5/Lv0PCvIQCgvuD2fkIQ7iHH+xlT22SdRmnq E7YAn0JmNbP22/rm6hwKPchNm1dbbXyj =zIOM -END PGP SIGNATURE- - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat and PermGen
Thanks for this link. Reading that page made me a little pessimistic. E On Mon, Nov 2, 2009 at 9:38 PM, Caldarale, Charles R chuck.caldar...@unisys.com wrote: From: Gerwood Stewart [mailto:gstew...@une.edu.au] Subject: RE: Tomcat and PermGen Do you know of any ways to track down what might be 'stuck' here or a starting point I could use? Take a look at this, although the thread you read probably covered much of it: http://opensource.atlassian.com/confluence/spring/pages/viewpage.action?pageId=2669 You're most likely going to have to slog through heap profiler output looking for objects (including java.lang.Class instances) that belong to the stopped webapp. They'll show up more readily if you just undeploy, not redeploy. - Chuck
Re: ConnectionPool question
No, you do not need to close the XXXMetaData classes. E On Tue, Nov 3, 2009 at 12:02 PM, Josh Gooding josh.good...@gmail.comwrote: One more question on bleeding resources. When closing RS / statement / connections. Do I have to do anything with the MetaData if I got that as well? (I.E Do I explicitly have to close the metadata as well?) Josh On Tue, Nov 3, 2009 at 2:01 PM, Josh Gooding josh.good...@gmail.com wrote: Elle, I am going to dig into this code and check it out. I want to know more about how to use threadlocal and filters. (Sorry I'm not as experienced in Tomcat as some for you gurus here). The code looks promising and I like the 2nd option due to the fact that each HTTP req. only has one connection (which should drop the overhead immensely) however for right now, I just want to fix the bleeding issue (which it seems that I have caught a good portion of them), so I'll use my legacy code, but during a minor code release, I can definitely look into rolling this out. I am getting a ton of abandoned connection warnings in the console window, so I need to find out where these are coming from now. I don't know where to begin thanking you guys but thank you. I've gotten more mentoring here on this listing than I have in 2 years at my current employer. Thank you all again. - Josh On Mon, Nov 2, 2009 at 3:40 PM, Christopher Schultz ch...@christopherschultz.net wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Elli, On 11/2/2009 4:08 AM, Elli Albek wrote: I think you can have a solution without changing your code. Try something like this: getConnection() static method should get the connection, and add it to a list that you keep in threadlocal. recycleConnection() should close the connection and remove the connection object from thread local. Add a servlet filter that closes all connections in thread local. The filter calls next filter, and in a finally block get the connections from thread local, close all of them, and clear the list in thread local. This is a horrible, nasty hack and it's entirely brilliant! I would change Elli's implementation just slightly, and actually write your own DataSource implementation that piggybacks on another one. Basically, you just wrap the DataSource that Tomcat provides either by: a. Using JNDI to look-up the Tomcat-created JNDI DataSource and just writing the plumbing code to pass everything through b. Actually subclass the DataSource class(es) provided by Tomcat and use /those/ in your Resource configuration. I would also not make any of this static... there's just no reason to do so, especially if your DataSource object is in the JNDI context. Although the /real/ solution is to fix the code, I really like this solution for a couple of reasons: 1. It requires no wrapping of Connection, Statement, etc. objects (which is entirely miserable if you've ever had to do it) 2. It requires no changes to your code whatsoever (if you use my DataSource-wrapping suggestion above) 3. You won't end up closing your connection, statement, result set, etc. too early because your code has completed execution (unless you are using JDBC resources across requests, which is another story) What this won't help, unfortunately is: * Closing your ResultSet and Statement objects (though this can be solved by wrapping the Connection, Statement, etc. objects handed- out by your DataSource. Yes, it's miserable.) This will allow you to keep your legacy code. As far as I remember DBCP has an option to close the result sets and statements when you close the connection. If not this will partly work. I don't believe commons-dbcp has this capability at all. I'm willing to read any documentation to the contrary, though. Version 2: Advanced Keep the actual connection in thread local. You will have one connection per HTTP request. getConnection() should be something like public static /* NOT synchronized */ Connection getConnection(){ Connection c = ...// get the connection from thread local if (c != null) return c; Connection c = ...// get the connection from JNDI/DBCP // put connection in thread local return c; } I like this technique, too. You just have to decide if it's acceptable for your webapp to re-use connections. I can't imagine why that would be a problem, but it's worth considering before you blindly do it. This optimization can save you from deadlock (though you're killing-off connections after 15 seconds anyway) and should significantly improve the performance of your webapp because you won't be bleeding so many connections: you're limited to bleeding one connection per request instead of potentially dozens. recycleConnection(){ // empty, connection will be recycled by filter
Re: ConnectionPool question
Here is some idea for you: First, you have two static methods to get and return the connection inside a listener class. Those methods do not have anything to do with the listener (which is an instance), and also and also do not need synchronization. Synchronizing on getConnection can be a big bottleneck, especially if you are doing a validation query onBorrow. Having said that, it sounds like this is the least of your problems now. I think you can have a solution without changing your code. Try something like this: getConnection() static method should get the connection, and add it to a list that you keep in threadlocal. recycleConnection() should close the connection and remove the connection object from thread local. Add a servlet filter that closes all connections in thread local. The filter calls next filter, and in a finally block get the connections from thread local, close all of them, and clear the list in thread local. This will allow you to keep your legacy code. As far as I remember DBCP has an option to close the result sets and statements when you close the connection. If not this will partly work. This is as close as you can get to having the connections reclaimed immediately without rewriting your application. Something like: public static /* NOT synchronized */ Connection getConnection(){ Connection c = ...// get the connection from JNDI/DBCP ListConnection connections = // get or create from thread local if(connections.contains(c) == false) // make sure c.equals() works as object reference equality, eg == // You may have to read DBCP code for this or add a break point and trace through the code until you get to equals() connections.add(c); if(myLogger.isDebug()) myLogger.debug(“Request consumed “+ list.size() + “ connection(s)”); return c; } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { try{ // handle request chain.doFilter(req, res); }finally{ ListConnection connections = ...// get from thread local if (connections != null){ for(Connection c: connections){ try{ c.close(); }catch(Throwable t){ myLogger.error(“Error on connection close”, t); } } connections.clear(); } } } public static synchronized void recycleConnection(Connection c) { ListConnection connections = ...// get from thread local connections.remove(c); try { c.close(); } catch (Throwable t) { // DO NOT eat the exception, especially when there are known issues in the connection management code myLogger.warn(“Error closing connection”, t); } } I also think that I have seen somewhere a configuration that does the above for you, but if not its not a lot of code to do yourself. Map the filter to all the URL mappings that can possibly can open connection, which in the worse case is /*. Notice that with the code sample you wrote, a typical application will consume many connections for one request (possible one per statement), and worse than that, will not be able to perform transactional writes (since each write is on a separate connection). Version 2: Advanced Keep the actual connection in thread local. You will have one connection per HTTP request. getConnection() should be something like public static /* NOT synchronized */ Connection getConnection(){ Connection c = ...// get the connection from thread local if (c != null) return c; Connection c = ...// get the connection from JNDI/DBCP // put connection in thread local return c; } recycleConnection(){ // empty, connection will be recycled by filter. } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { try{ // handle request chain.doFilter(req, res); }finally{ ListConnection connections = ...// get from thread local if (connections != null){ for(Connection c: connections){ try{ c.close(); }catch(Throwable t){ myLogger.error(“Error on connection close”, t); } } connections.clear(); } } } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { try{ // handle request chain.doFilter(req, res); }finally{ Connection c = ...// get and REMOVE from thread local if (c != null){ try{ c.close(); }catch(Throwable t){ myLogger.error(“Error on connection close”, t); } } } } The filter is the same, but not using lists. Version 2 will give you one connection per servlet request, which normally I would not do for a well written DAO code, but in your case you are not really dealing with such code. You can get large performance boost by having one
Re: ConnectionPool question
Oops, I had a copy paste error. Version 2 has the filter method twice. Ignore the first, use the second. Notice this code was written in an email client, not an IDE :) E
Re: starting tomcat from ant not working
Hi, This is how we start tomcat from ant. ${server} is your tomcat installation directory. Then we have a condition on a URL, so we know tomcat actually starts and handling HTTP requests. java jar=${server}/bin/bootstrap.jar fork=true spawn=true dir=${server}/bin jvmarg value=-Dcatalina.home=${server} / arg line=start / /java Notice the startup folder and catalina home argument. This is to avoid conflicts with other tomcat installations that may be on the system. E On Sun, Nov 1, 2009 at 9:16 PM, Dean Hiller d...@alvazan.com wrote: I have tried from ant and programmed up a main class to start tomcat via catalina.bat start and tried catalina.bat start from ant as well. Lastly, I finally tried directly running the exact command that catalina.bat start tries to run and then ended up with classnotfound which makes no sense since I thought the bootstrap class is supposed to put that together.(any ideas?)
Re: [OT] Hammers and nails (was Re: A question about log-rotation on catalina.out)
How did this make it into the tomcat users list? :) CPAN: Driven by users. Java (JCP) Driven by vendors.
Re: Tomcat Memory and Garbage Collection questions...
A question: Do you guys use hot deployment of applications? If you do *not*, then Joseph’s tips are the first things to look at, in short it is the application code keeping too many references. If you do hot deployment, then the number of possibilities goes up significantly. Now you are also talking about references to class loaders and memory cleanup at shutdown, which is another topic altogether. E On Mon, Nov 2, 2009 at 1:44 PM, Joseph Morgan joseph.mor...@ignitesales.com wrote: I hope Mr. Caldarale answered your question, because you may otherwise be looking at the 800lb Gorilla in the room. Memory problems within Tomcat could be a number of very hard to see things, but some quick candidates are: * Programmers caching too much data from the DB (or file system) into context attributes * Programmers using context attributes to store session data * Programmers pushing too much data into session attributes * Session timeout is set too high and sessions aren't timing out
Re: DBCP woes (running out of cursors).
Hi, From what I can remember, which has been a long time ago, requests are being handled by servlets after the shutdown process has started and the pool was closed. I would imagine that this is a violation of the spec as well, but I am not sure. You would imagine that JNDI resources should be available for the web app until it is closed, as well as during the shutdown process. Context listeners should be able to access the pool via JNDI even during shutdown. The problem with about to be shut down is that it is not fully shut down. It is not shut down at least in the sense that the context listener is running. There may be another listener that tries to use the database for flushing asynch writes. So I rather keep connection management outside of the app. Thats why the tomcat listener seems like a better choice, especially when there is a dedicated event for after stop. From the testing, after stop is truly the last event in the chain and runs after the web app is completely shut down and all its internal listeners are called. In other words, objects that are started outside the app should not be shut in from within the app if possible. The web app should only stop what it starts by itself. E On 10/28/09, Christopher Schultz ch...@christopherschultz.net wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Elli, On 10/28/2009 12:21 AM, Elli Albek wrote: In terms of listeners, I saw that Tomcat executes requests while in the closing process. That's a problem. What kind of listener are you using? My understanding was that: 1. Tomcat does not remove the connection pool 2. Once the shutdown process has started, no new requests will be handled by the currently-shutting-down context Could these two items give the result you are observing? It's easy enough to have your webapp close the DataSource (even though it's kinda stupid that Tomcat doesn't do it for you). That depends on which shutdown it is. Understanding 2 is not correct from my debugging. You can have a sequence of: 1. Connection pool closed 2. Request sent to servlet The documentation for ServletContextListener.contextDestroyed says: Notification that the servlet context is about to be shut down. All servlets and filters have been destroy()ed before any ServletContextListeners are notified of context destruction. Assuming that servlets aren't being re-initialized to service new requests, using a ServletContextListener ought to work in this case. I'm happy to hear an explanation for why my assumption isn't true, but this woul dbe my expectation. If your webapp is handling requests after the ServletContextListener.contextDestroyed method is called, I would consider that a violation of the servlet specification. If you want to add a listener that closes the pool, I would try adding tomcat lifecycle listener to the context. You can handle event Lifecycle.AFTER_STOP_EVENT. Try both listeners (web app and tomcat) and see which one runs last, and put the code there. I'm guessing that Tomcat's listener would execute after the ServletContextListener, since AFTER_STOP_EVENT indicates that the stop has occurred, while the servlet-API listener says it is about to be shut down. Then the vision of J2EE designers of separation of roles materializes :) Something tells me those guys didn't exactly invent the concept of separation of roles. - -chris -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.10 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkrodboACgkQ9CaO5/Lv0PAhGQCgooVyE8753TIz635X2lSvZJOV j8cAoJnX6kDBSuBscVlwjEX0kZ5SlAun =u9j7 -END PGP SIGNATURE- - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: DBCP woes (running out of cursors).
Thanks for your replies. I agree that Tomcat should be responsible for all objects that are configured in Tomcat, and the web app should be responsible for objects that are created by the webapp. Currently it does not happen properly in tomcat. This is not related to DBCP code, it is all Tomcat code. In terms of listeners, I saw that Tomcat executes requests while in the closing process. This may mean that after the context listener closed the pool, a new request will cause it to initialize again. We had a similar problem of things being created after shutdown started, and there are many permutations of listeners and sequences to test. Lots of debugging to do here. This again is irrespective of the listener which I am sure is closing the connection pool, it is a tomcat lifecycle issue. It is built into Tomcat. Just read the docs for JDBC DataSources: http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html I am talking about something else. Basically the XML is short: GlobalNamingResources Resource auth=Container type=javax.sql.DataSource propertiesFile=database_pool_configuration_file.properties / /GlobalNamingResources No configuration in XML other than JNDI related bindings. My understanding was that: 1. Tomcat does not remove the connection pool 2. Once the shutdown process has started, no new requests will be handled by the currently-shutting-down context Could these two items give the result you are observing? It's easy enough to have your webapp close the DataSource (even though it's kinda stupid that Tomcat doesn't do it for you). That depends on which shutdown it is. Understanding 2 is not correct from my debugging. You can have a sequence of: 1. Connection pool closed 2. Request sent to servlet This happens during tomcat shutdown and will trigger a new connection. I suspect that similar sequence exists during redeploy. I cant recall exactly what happened in this case, but I remember that it was in more than one scenario. We decided to shut down tomcat every time and forget about it, even though we do have a listener that closes pools, along the same lines as the listener that you wrote I imagine. If you want to add a listener that closes the pool, I would try adding tomcat lifecycle listener to the context. You can handle event Lifecycle.AFTER_STOP_EVENT. Try both listeners (web app and tomcat) and see which one runs last, and put the code there. You have higher probability of catching an open connection if you do it later. If the listener is configured via tomcat and not the web app, you also get a configuration that each party is responsible for cleaning up its own bugs, as opposed to web app cleaning up tomcat bugs. Then the vision of J2EE designers of separation of roles materializes :) Elli - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: DBCP woes (running out of cursors).
Hi, I did not follow this thread form the beginning, but I can provide a few tips about using connection pools in tomcat. 1. DBCP has quite a few problems in the area of scalability. We have our own modified version of the source that makes it more concurrent, and I believe some of those changes were integrated into DBCP. Use the latest stable version of DBCP form the commons project. It is a jar file in tomcat that you can easily replace. The fixes do not require using concurrent, that part of the code is not causing the problems. 2. If your JDBC driver supports caching of prepared statements and metadata, do it in the driver and disable this in DBCP. IMO DBCP does a poor job at best in caching. We use mysql and its JDBC driver is doing an excellent job. 3. Your JDBC driver may already be caching metadata that DBCP is caching. In this case you are caching the same data twice. Make sure it dose not happen, it is a big memory overload on the JVM. 4. Tomcat has a problem doing a clean shutdown of DBCP, and other JNDI resources. I traced in the debugger dangling connection pools that are created during the shutdown process. If your pool is configure to ping the connections once in a while, they can stay open for a long time, possibly forever. Our solution is custom extension that cleans up pools, which works in conjunction with our extended implementation of DBCP. 5. The connection pool leak is caused mostly when war files are replaced under load. If you are experiencing a problem of leaks in those conditions, then some common options are: A. Write custom extension to the pooling mechanism as we did. This is not a 100% solution. B. Avoid hot deployment of apps by shutting down tomcat before updates. This is safer, but also not 100% clean. C. Block Tomcat during the update. If you have a load balancer, redirect traffic to other tomcat instances, and then do the update while tomcat has no load. This reduces the problems significantly. When you do a full tomcat shutdown, there will still be connections that are not closed, but the process itself will finish, and the database will clean up the connections after some time. This is of course not as clean as closing all the connections on server shutdown, but I don't know of any better option. I believe our custom cleanup code does close most connections on shutdown, but I have no 100% certainty or evidence that this is actually true. However it does do a lot of closing that did not happen before. I am not aware of any way to completely avoid dangling connection pool after hot deployment under load. We tried to fix this but it got too complicated, it is much easier to restart Tomcat and swallow the bitter pill. You can still do hot deployment of war files that do not access the database, though it is possible that the same leaks will leave lots of hanging objects of other types (like email clients, JMS clients, thread pools, HttpClient, etc). E On 10/26/09, Mark Thomas ma...@apache.org wrote: Bill Davidson wrote: Christopher Schultz wrote: When you've played with it for a bit, tell us how things turned out. It's looking like optimal is caching about 40 PreparedStatement objects. However, I should qualify that noting that it's with our application and specifically with our little pummeling benchmark, which requests a specific subset of services, and probably isn't even a great test of real world traffic. It was mainly designed to see how the app handled being heavily stressed (like getting hit with 1000 requests at a time). The system is still about 3-4% slower with DBCP than with our old pooling library. Our old pooling library did not wrap the Connection objects like DBCP does, though it did close old Connection objects so that they only got reused for up to two minutes at a time. I'm actually a little surprised by this. I would have expected that to make DBCP faster, since it keeps them open. The current DBCP (actually commons-pool) can struggle under very heavy load in multi-thread environments. There are plans afoot for a pool 2.0 that will be based on java.util.concurrent that should enable much better multi-threaded performance. As always, it is best to check with a profiler to see what is actually slowing you down. Mark - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: DBCP woes (running out of cursors).
Hi, More information about tomcat shutdown and object swapping probably belongs in the development list. It is quite a bit of work to extend DBCP and write extensions to tomcat, and at the end of the day most of those problems I would consider as bugs. DBCP specifically cannot be easily extended, we had to use the original source files with some modifications, my least favorite option. MySQL documentation covers their JDBC client configuration very well. The number of options is little overwhelming, but after some time and a few tests it is possible to find a configuration that is a match to the system resources. See: http://dev.mysql.com/doc/refman/5.1/en/connector-j-reference-configuration-properties.html The configuration is version specific, find your version before reading. About the database clearing up dangling connections, you will have to read the database documentation. I hate to say RTFM, but there is nothing else I can say here :) To disable caching in DBCP, use configuration option: poolPreparedStatements=false I don’t remember where exactly you specify it, since our extension just passes a property file to DBCP. This is actually something that I would like to see built into Tomcat/DBCP (property file configuration). Your system admin will thank you. To troubleshoot where caching is being done, your best bet is stepping through the code with a debugger. Make sure the configuration of the test system mirrors the production system. It may not be possible to use the mysql caching algorithms, since they may use features that are not publicly available through JDBC and are part of their protocol. I don’t know the source well enough to comment on how it works internally. Specific example of leaks: 1.Close tomcat 2.Connection pool is removed. 3.Request comes in to the war file (the one that is in the closing process) 4.Request gets processed. 5.Servlet needs a connection from DBCP. 6.Tomcat does not find the DBCP pool in JNDI, so it recreates it. 7.The newly created connection pool will not be used after this request, and will not be closed. If the pool pings the connection, it will stay open. A similar path I believe exists while hot deploying a war file, which also exhibits the problem of handling requests in the middle of shutdown. It has been a while since we worked on it, the details may vary from what is listed above. However, one thing I do remember is that after some objects were shut down Tomcat was still processing requests that required those objects, and there was more than one way to reproduce it. After all this work, we just shut down tomcat when we update war files. It is possible to fix this. Two things that I would start with: 1.Standard server shutdown order. This is too much information for this list. 2.Call shutdown callbacks of different APIs, give developer an option to deal with it. For example JMX shutdown process does not happen correctly. You may be able to fix this via listeners on various levels. We got to the conclusion that shutting down objects in tomcat was little chaotic and no one could say in confidence that using a certain listener API will work better than another without spending a few days of tracing the code and doing lots of tests. The problem is that in a simple invocation everything seems to work fine, but if you throw in a few threads and methods that take some time to respond then tracing becomes complicated and time intensive. From my past experience multithreaded debugging can be time intensive, especially when it involves so many components and possible paths as we have in a full blown application container. To make a long story short: 1.Disable caching in DBCP 2.Enable caching in your JDBC client 3.Shut down tomcat when you replace war files or when you change configuration. Elli On Mon, Oct 26, 2009 at 6:54 PM, Martin Gainty mgai...@hotmail.com wrote: mggood work From: e...@sustainlane.com To: users@tomcat.apache.org Hi, I did not follow this thread form the beginning, but I can provide a few tips about using connection pools in tomcat. 1. DBCP has quite a few problems in the area of scalability. We have our own modified version of the source that makes it more concurrent, and I believe some of those changes were integrated into DBCP. Use the latest stable version of DBCP form the commons project. It is a jar file in tomcat that you can easily replace. The fixes do not require using concurrent, that part of the code is not causing the problems. 2. If your JDBC driver supports caching of prepared statements and metadata, do it in the driver and disable this in DBCP. IMO DBCP does a poor job at best in caching. We use mysql and its JDBC driver is doing an excellent job. mgis it possible to port the working (MySQL) Driver caching algorithms to DBCP? 3. Your JDBC driver may already be caching metadata that DBCP is caching. In this case you are
Re: How to know when tomcat is ready to serve request
Notice that server life cycle listeners normally work in the server context, and not in a war file class loader. This may cause some problems for code in the war file accessing the objects that were created by the listener. Something else that you should consider in tomcat 5.x versions is the shutdown, which may cause requests to be processed in the middle of shutdown, after some components were already stopped (meaning their shutdown callback method was called, and they released their resources). In JNDI it will cause released objects to re-instantiate themselves. So if you see your thread pool restarting after you issue a shutdown command under load, don't be surprised. The safest way I know around it is not have container based shutdown methods on the objects. Instead have a server lifecycle listener shut them down using proprietary methods that are not defined by the container interfaces (which you should implement as empty methods). E - Original Message - From: Anup K Ram anupk...@gmail.com To: Tomcat Users List users@tomcat.apache.org Sent: Thu, 22 Oct 2009 20:58:37 -0700 (PDT) Subject: Re: How to know when tomcat is ready to serve request My problem here is I want to wake up the thread after the server is completely started. I have not used Server LifeCycleListener before. I will give it a try. Appreciate any help. Thanks. On Thu, Oct 22, 2009 at 7:48 PM, Elli Albek e...@sustainlane.com wrote: If this is the case you can assume that the war file is deployed. I don't trust the code of the tomcat startup/shutdown. If you want to be 100% safe use a server lifecytle listener. This is limited to a server that has the same apps, meaning you are not adding/removing/replacing applications on the fly. There is a higher probability that what you assume is running and not running based on event listeners is correct with lifecycle listener (higher, not 100%). This is for tomcat 5.x. in 6.x versions the event and lifecycle management may mirror more the actual lifecycle of objects. E - Original Message - From: Anup K Ram anupk...@gmail.com To: Tomcat Users List users@tomcat.apache.org Sent: Thursday, October 22, 2009 9:38:01 AM (GMT-0800) America/Los_Angeles Subject: Re: How to know when tomcat is ready to serve request The code is in a thread thats in turn spawned from the contextInitilized method of a ServletContextListener.(Inside the war) On Wed, Oct 21, 2009 at 11:53 PM, Elli Albek e...@sustainlane.com wrote: Where does the code that needs to know that reside? How is it initialized? Is it inside tomcat (war file, valve, JNDI resource) or outside the tomcat JVM? - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How can I prevent Quartz multiple execution after tomcat restart
Where is your spring configuration file? Is it inside the war file? When you have two hosts, do you have the war file in both? If this is he case you may deploy the entire war file twice. Generally a deployed war file can run only in one host. If you run it in two hosts, you are deploying the entire war file twice. This will create two instances of your quartz object. If all you need is multiple domains mapped to the same application, try replacing Host name=localhost ../Host Host name=XXX.com../Host With: Host name=localhost ... AliasXXX.com/Alias .../Host E - Original Message - From: zlzc2000 zlzc2...@hotmail.com To: users@tomcat.apache.org Sent: Fri, 23 Oct 2009 00:28:16 -0700 (PDT) Subject: How can I prevent Quartz multiple execution after tomcat restart hallo, we have problem with Quartz and Tomcat. Im using tomcat 5.5 i using 'localhost' to deploy a Spring project on server. after deploy run Quartz the job once time. this is right. but after restart tomcat, execute the same jobs twice at the same time. (project new deploy then no problem, only after tomcat stop-start or restart, then comming problem) (2 quartz instanz created and started) in server.xml i use two Host tags 1: Host name=localhost ... 2:Host name=XXX.com... if i use only one host, for example only Host name=XXX.com..., then no problem., but by which i can not use interface of tomcat. a strange thing: in tomcat management interface i have stoped project, but even though, in catalina.out can ich see, there is still one quartz job run. I CANT UNDERSTAND! how can i prevent it? follow code are our server.xml code Host name=localhost appBase=webapps unpackWARs=true autoDeploy=false xmlValidation=false xmlNamespaceAware=false /Host Host name=XXX.com unpackWARs=true autoDeploy=false deployOnStartup=false xmlValidation=false xmlNamespaceAware=false Aliaswww.XXX.com/Alias Context path= docBase=/var/lib/tomcat55/webapps/xxx reloadable=true Realm className=org.apache.catalina.realm.JDBCRealm driverName=org.postgresql.Driver connectionURL=jdbcostgresql://localhost:5432/xxx connectionName=postgres connectionPassword= userTable=users_password userNameCol=userid userCredCol=password userRoleTable=user_role roleNameCol=rolename digest=MD5/ /Context /Host ... follow code are configuration of Quartz in applicationContex.xml bean id=robotSearchSwapper class=org.springframework.scheduling.quartz.Metho dInvokingJobDetailFactoryBean property name=targetObject ref bean=swapperService / /property property name=targetMethod valuerobotSearch/value /property property name=concurrent value=false / /bean bean id=robotSearchTrigger class=org.springframework.scheduling.quartz.Simpl eTriggerBean property name=jobDetail ref=robotSearchSwapper/ property name=startDelay value18/value /property property name=repeatInterval value30/value /property /bean bean id=scheduler class=org.springframework.scheduling.quartz.Sched ulerFactoryBean property name=quartzProperties props prop key=org.quartz.threadPool.classorg.quartz.simpl .SimpleThreadPool/prop prop key=org.quartz.threadPool.threadCount1/prop prop key=org.quartz.threadPool.threadPriority1/prop prop key=org.quartz.threadPool.threadsInheritContextCl assLoaderOfInitializingThreadtrue/prop /props /property property name=triggers list ref local=robotSearchTrigger/ /list /property /bean -- View this message in context: http://www.nabble.com/How-can-I-prevent-Quartz-multiple-execution-after-tomcat-restart-tp26021949p26021949.html Sent from the Tomcat - User mailing list archive at Nabble.com. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Does Tomcat http support subdomains?
My initial response to that article is that it's vague drivel. If you are an incredibly savvy and experienced web developer, no doubt you already have a DreamHost account - should be all you need to read to make a reasonable critical assessment of the quality of this article. :) - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Cannot set remote address in valve (Tomcat 5.5)
Makes sense. I did not dig through the code of the full version RemoteIpValve so much, just enough to get the general idea (or maybe just enough to get into trouble). I have to look at the docs of our load balancer or maybe just add the proto header to the log files to see what values it gets. I know that with squid we are fine, and the server is generally accessible only through the load balancer or reverse proxy. If I can make a suggestion for the docs on google code, be specific that this valve should be in the engine and precede all other elements of the engine. This makes everything work smoothly. It may also be possible to put it outside the engine, not sure if that is a general safe case. I think the only real solution here is as you implemented, a valve that precedes log valves and other valves (many of which use the IP). Keeps the rest of the code clean and simple, the configuration is in one place instead of all over the place. By the way is it proxied or proxyfied request? :) E - Original Message - From: Cyrille Le Clerc clecl...@xebia.fr To: Tomcat Users List users@tomcat.apache.org Sent: Wed, 21 Oct 2009 06:31:57 -0700 (PDT) Subject: Re: Cannot set remote address in valve (Tomcat 5.5) Hello Elli, From what I understand of your architecture, I would configure RemoteIpValve with : Valve className = org.apache.catalina.connector.RemoteIpValve internalProxies = @load-balancer-ip trustedProxies = @the-trusted-proxy-that-is-not-the-load-balancer protocolHeader = x-forwarded-proto / Note : - do not forget to regexp escape' the ip adresses in internalProxies and trustedProxies attributes. - do not declare protocolHeader=x-forwarded-proto if your load balancer do not manage it - more docs at http://code.google.com/p/xebia-france/wiki/RemoteIpValve Thanks to this, - the 99% direct requests will reach Tomcat with x-forwarded-for=@clientIp - 1% proxyfied requests will reach Tomcat with x-forwarded-for=@clientIp, @the-trusted-proxy-that-is-not-the-load-balancer Does it make sense ? Cyrille -- Cyrille Le Clerc clecl...@xebia.fr cyri...@cyrilleleclerc.com http://blog.xebia.fr On Wed, Oct 21, 2009 at 6:57 AM, Elli Albek e...@sustainlane.com wrote: A question: How do you know that a proxy is trusted? Is it by providing a list of trusted IPs in the configuration of the filter? Our load balancer is always adding the client IP as the first in the list, and it does not add its own IP to the list. The header has one IP +99% of the times, the other times there is an additional IP of a proxy that is not our load balancer (reverse proxy). So in that case, we can check that the request comes from a trusted IP list (known load balancers), and only then try to change the IP. If the client IP does not come from the load balancer, it is basically a pass through. For our system the first IP is what the load balancer sees, and the only way to spoof it is to access the server not through the load balancer. If you send a request with a spoofed header to the laod balancer, it will still add the IP of the spoofer in the beginning of the list. This may not be the general case for proxies, it is only for this case. E -Original Message- From: Cyrille Le Clerc [mailto:clecl...@xebia.fr] Sent: Thursday, October 08, 2009 1:04 AM To: Tomcat Users List Subject: Re: Cannot set remote address in valve (Tomcat 5.5) Hello Elli, I am afraid there may be a flaw in the algorythm looking for the first IP of the coma delimited x-forwarded-for header without ensuring that this first IP has been set by a trusted proxy and not by the requester ( getFirstIP(xforwardedForHeaderValue) ). Such spoofing can easily be achieved with tools like Firefox add-ons Modify Headers (1) and X-Forwarded-For Spoofer (2) . The forthcoming version of Apache Httpd will offer a secure mechanism to handle X-Forwarded-For with a module called mod_remoteip (3). It relies on the concept of trusted proxies which IP address can be 'swallowed'. The first IP of the list that is not a trusted proxy is seen as the real remote ip. mod_remoteip would not have been tricked by such x-forwarded-for header spoofing. Here are two java ports of mod_remoteip to handle X-Forwarded-For at the Tomcat level with a valve and at the WAR level with a servlet filter : RemoteIpValve (4) and XForwardedFilter (5). In addition to handle X-Forwarded-For, they also integrate X-Forwarded-Proto (ssl). These java ports integrate the same trusted proxies concept to prevent spoofing. Cyrille -- Cyrille Le Clerc clecl...@xebia.fr cyri...@cyrilleleclerc.com http://blog.xebia.fr (1) https://addons.mozilla.org/en-US/firefox/addon/967 (2) https://addons.mozilla.org/en-US/firefox/addon/5948 (3) http://httpd.apache.org/docs/trunk/mod/mod_remoteip.html (4) http://code.google.com/p/xebia-france/wiki/RemoteIpValve (5) http://code.google.com/p/xebia-france/wiki
Re: How to know when tomcat is ready to serve request
Where does the code that needs to know that reside? How is it initialized? Is it inside tomcat (war file, valve, JNDI resource) or outside the tomcat JVM? E - Original Message - From: Anup K Ram anupk...@gmail.com To: users@tomcat.apache.org Sent: Wed, 21 Oct 2009 16:56:50 -0700 (PDT) Subject: How to know when tomcat is ready to serve request Hi, Is there a way to know whether tomcat is started successfully and ready to serve requests? I need to know this programmatically. Thanks In Advance. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Valves being converted to Filters?
This is my concern as well. Our custom login valve is using values from the form authentication valve that are not accessible in the war file. For example they allow reconstruction of a post request and replacing roles and principals, which I doubt can be done with a filter in a simple way without repeating a lot of code. Even though there is a lot in common, I would like to have access to the tomcat internal data and not be limited to the application level API. Valve cam use HttpServletRequest and response, if you know that you can cast them to an internal class with the full API. In that case it may be safer to just use that class in the method signatures. E - Original Message - From: Christopher Schultz ch...@christopherschultz.net To: Tomcat Users List users@tomcat.apache.org Sent: Wed, 21 Oct 2009 08:11:17 -0700 (PDT) Subject: Re: Valves being converted to Filters? Will there be a way to grab information from the raw request as seen by a Valve today? It's nice to be able to get and set values above (or below, depending on your POV) the servlet API. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to know when tomcat is ready to serve request
If this is the case you can assume that the war file is deployed. I don't trust the code of the tomcat startup/shutdown. If you want to be 100% safe use a server lifecytle listener. This is limited to a server that has the same apps, meaning you are not adding/removing/replacing applications on the fly. There is a higher probability that what you assume is running and not running based on event listeners is correct with lifecycle listener (higher, not 100%). This is for tomcat 5.x. in 6.x versions the event and lifecycle management may mirror more the actual lifecycle of objects. E - Original Message - From: Anup K Ram anupk...@gmail.com To: Tomcat Users List users@tomcat.apache.org Sent: Thursday, October 22, 2009 9:38:01 AM (GMT-0800) America/Los_Angeles Subject: Re: How to know when tomcat is ready to serve request The code is in a thread thats in turn spawned from the contextInitilized method of a ServletContextListener.(Inside the war) On Wed, Oct 21, 2009 at 11:53 PM, Elli Albek e...@sustainlane.com wrote: Where does the code that needs to know that reside? How is it initialized? Is it inside tomcat (war file, valve, JNDI resource) or outside the tomcat JVM? - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Starting web app with properties set
Load the properties using java.util.Properties, and store them in a place that is accessible in the war (like a static variable or context attribute). If you are thinking about properties such as database/mail server connections, then keep the OUTSIDE of the war file, not in XML or other things that will require your sys admin to open war files and change them, or mix tomcat configuration with application database connection properties, etc. A good place for you property files is [tomcat]/shared/classes. Property files in this folder are accessible to the war files via the standard class loader. The down side is that the same file is accessible to all, so if you need a separate configuration for each war you will have to use different file names. E - Original Message - From: Ken T. ktectr...@gmail.com To: users@tomcat.apache.org Sent: Thursday, October 22, 2009 9:58:33 AM (GMT-0800) America/Los_Angeles Subject: Starting web app with properties set I looked around online but couldn't find anything. Is there a way to start a web application under Tomcat with specific properties mappings. Say I wanted to start my app with the property setting: user.database=ProdDB How would I go about doing so? Thank you, -- Ken T. ktectr...@gmail.com - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
RE: Valves being converted to Filters?
So is there still going to be an API to plug into the tomcat internals and do things that the servlet API does not support? E -Original Message- From: Cyrille Le Clerc [mailto:clecl...@xebia.fr] Sent: Tuesday, October 20, 2009 4:06 PM To: Tomcat Users List Subject: Re: Valves being converted to Filters? Hello Henri, I was referring to public information such as : - Google Summer Of Code 2009, project Convert current Tomcat valves to Servlet Filters : http://wiki.apache.org/tomcat/SummerOfCode2009 and the various associated emails on Tomcat dev mailing list. - Mark Thomas post on Tomcat users mailing list : ...47330 is on the todo list but my current plan is to implement it as a Filter rather than a valve. (1) However, my understanding is not that pluggable 'interceptors' will be removed from the container, just that the Valve API will be replaced with a Filter API. I feel interfaces (HttpServletRequest HttpServletResponse) will be much more easy to manipulate than the current implementations (Request, Response). Hopr this clarifies my message, Cyrille - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
RE: Cannot set remote address in valve (Tomcat 5.5)
A question: How do you know that a proxy is trusted? Is it by providing a list of trusted IPs in the configuration of the filter? Our load balancer is always adding the client IP as the first in the list, and it does not add its own IP to the list. The header has one IP +99% of the times, the other times there is an additional IP of a proxy that is not our load balancer (reverse proxy). So in that case, we can check that the request comes from a trusted IP list (known load balancers), and only then try to change the IP. If the client IP does not come from the load balancer, it is basically a pass through. For our system the first IP is what the load balancer sees, and the only way to spoof it is to access the server not through the load balancer. If you send a request with a spoofed header to the laod balancer, it will still add the IP of the spoofer in the beginning of the list. This may not be the general case for proxies, it is only for this case. E -Original Message- From: Cyrille Le Clerc [mailto:clecl...@xebia.fr] Sent: Thursday, October 08, 2009 1:04 AM To: Tomcat Users List Subject: Re: Cannot set remote address in valve (Tomcat 5.5) Hello Elli, I am afraid there may be a flaw in the algorythm looking for the first IP of the coma delimited x-forwarded-for header without ensuring that this first IP has been set by a trusted proxy and not by the requester ( getFirstIP(xforwardedForHeaderValue) ). Such spoofing can easily be achieved with tools like Firefox add-ons Modify Headers (1) and X-Forwarded-For Spoofer (2) . The forthcoming version of Apache Httpd will offer a secure mechanism to handle X-Forwarded-For with a module called mod_remoteip (3). It relies on the concept of trusted proxies which IP address can be 'swallowed'. The first IP of the list that is not a trusted proxy is seen as the real remote ip. mod_remoteip would not have been tricked by such x-forwarded-for header spoofing. Here are two java ports of mod_remoteip to handle X-Forwarded-For at the Tomcat level with a valve and at the WAR level with a servlet filter : RemoteIpValve (4) and XForwardedFilter (5). In addition to handle X-Forwarded-For, they also integrate X-Forwarded-Proto (ssl). These java ports integrate the same trusted proxies concept to prevent spoofing. Cyrille -- Cyrille Le Clerc clecl...@xebia.fr cyri...@cyrilleleclerc.com http://blog.xebia.fr (1) https://addons.mozilla.org/en-US/firefox/addon/967 (2) https://addons.mozilla.org/en-US/firefox/addon/5948 (3) http://httpd.apache.org/docs/trunk/mod/mod_remoteip.html (4) http://code.google.com/p/xebia-france/wiki/RemoteIpValve (5) http://code.google.com/p/xebia-france/wiki/XForwardedFilter On Mon, Oct 5, 2009 at 11:19 PM, Elli Albek e...@sustainlane.com wrote: Hi, We can add the header to the custom valves, but then in addition we have to change a few log file configurations, create a servlet filter and maybe something else I cant think of now. Basically doing the same thing a few times and keeping track of all the places that depend on the header. Ideally this would all be corrected once in the beginning of the request processing pipeline, so log file configuration, other valves and the war files will remain unchanged. Attached a Valve that does that. This is the minimum code necessary, so it should not have any significant performance impact. Feel free to use as is, not guaranteed to work, no expressed on implied warranties, not FDIC insured and may loose value. To configure Tomcat add to server.xml: Service name=Catalina Connector port=8080 .../ Engine defaultHost=localhost name=Catalina !-- This should precede all other configuration in the engine -- Valve className=org.apache.catalina.connector.RemoteIPValve/ Java class/jar should be placed in /server/lib or /server/classes E package org.apache.catalina.connector; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.ServletException; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.valves.ValveBase; /** * A valve that extracts the remote IP of the client from an HTTP header field * passed by the proxy, and set it in the request as the original client IP. * This valve should be the first valve in the engine, so log valves (and * others) will see the real client IP without requiring the same code again. * * @author Elli Albek, www.sustainlane.com */ public class RemoteIPValve extends ValveBase { private static final Pattern ipExpr = Pattern.compile(^[\\da-fA-F]+(\\.[\\da-fA-F]+)+); private String forwardedForHeader = X-Forwarded-For; public void invoke(Request request, Response response) throws IOException, ServletException { String header = request.getHeader
Re: Cannot set remote address in valve (Tomcat 5.5)
- Original Message - From: Christopher Schultz ch...@christopherschultz.net To: Tomcat Users List users@tomcat.apache.org Sent: Fri, 2 Oct 2009 07:32:06 -0700 (PDT) Subject: Re: Cannot set remote address in valve (Tomcat 5.5) 2. There are other valves like request filters that cannot work without the correct IP, as well as custom login valve. Filters should be OK providing they are defined in the right order. Aren't all Valves always called before Filters? To be more specific, i was referring to a request filter that is implemented as a valve, not as a servlet filter. One is shipped with tomcat already for filtering IPs. That valve does not work behind a load balancer or a reverse proxy. E - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Cannot set remote address in valve (Tomcat 5.5)
To make it clear, valves are executed around the web apps, so they are executed before the request gets to any servlet filter. Servlet filter behavior is defined by the Servlet specification. Valves are tomcat specific classes that contain some core server functionality that is not defined by the spec as an interface. E - Original Message - From: Tim Funk funk...@apache.org To: Tomcat Users List users@tomcat.apache.org Sent: Fri, 2 Oct 2009 07:46:14 -0700 (PDT) Subject: Re: Cannot set remote address in valve (Tomcat 5.5) Context filters are executed before webapp filters. I believe (but not confirmed) that valves execute before the filters. -Tim Christopher Schultz wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Mark, On 10/2/2009 5:55 AM, Mark Thomas wrote: Elli Albek wrote: A few reasons why not to do this as a servlet filter: 1. There are many web apps on the server and I don't want to include the filter in each. You don't have to. Configure it in the global web.xml. Are the filters configured in conf/web.xml considered before those in WEB-INF/web.xml... that is, will they be called before the webapp-defined ones? 2. There are other valves like request filters that cannot work without the correct IP, as well as custom login valve. Filters should be OK providing they are defined in the right order. Aren't all Valves always called before Filters? - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
RE: Cannot set remote address in valve (Tomcat 5.5)
Hi, We can add the header to the custom valves, but then in addition we have to change a few log file configurations, create a servlet filter and maybe something else I cant think of now. Basically doing the same thing a few times and keeping track of all the places that depend on the header. Ideally this would all be corrected once in the beginning of the request processing pipeline, so log file configuration, other valves and the war files will remain unchanged. Attached a Valve that does that. This is the minimum code necessary, so it should not have any significant performance impact. Feel free to use as is, not guaranteed to work, no expressed on implied warranties, not FDIC insured and may loose value. To configure Tomcat add to server.xml: Service name=Catalina Connector port=8080 .../ Engine defaultHost=localhost name=Catalina !-- This should precede all other configuration in the engine -- Valve className=org.apache.catalina.connector.RemoteIPValve/ Java class/jar should be placed in /server/lib or /server/classes E package org.apache.catalina.connector; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.ServletException; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.valves.ValveBase; /** * A valve that extracts the remote IP of the client from an HTTP header field * passed by the proxy, and set it in the request as the original client IP. * This valve should be the first valve in the engine, so log valves (and * others) will see the real client IP without requiring the same code again. * * @author Elli Albek, www.sustainlane.com */ public class RemoteIPValve extends ValveBase { private static final Pattern ipExpr = Pattern.compile(^[\\da-fA-F]+(\\.[\\da-fA-F]+)+); private String forwardedForHeader = X-Forwarded-For; public void invoke(Request request, Response response) throws IOException, ServletException { String header = request.getHeader(forwardedForHeader); String forwardedIP = getFirstIP(header); if (forwardedIP != null) request.remoteAddr = forwardedIP; next.invoke(request, response); } /** * Return the first IP address in a string that may contain an IP list */ static final String getFirstIP(String header) { if (header == null) return null; Matcher m = ipExpr.matcher(header); if (m.find()) { return m.group(); } return null; } public void setForwardedForHeader(String forwardedForHeader) { this.forwardedForHeader = forwardedForHeader; } public String getInfo() { return RemoteIPValve; } }
RE: Cannot set remote address in valve (Tomcat 5.5)
Yes, the remoteAddress member is protected. So you can only access it if you put your class in the same package. I thought of doing it like a filter (wrapping) but it does not look like a workable solution in this case. 1. The request class is final (which basically ends the discussion :) 2. This class is not a simple placeholder for values or a wrapper. It is a heavy object that is recycled at the end of the request processing and contains a lot of code. I don't have any intention to get into Tomcat internal resource management and object recycling code. It seems pretty complicated. I don't think you can just replace a server object as you can do with a servlet request wrapper that is basically a proxy. E -Original Message- From: Christopher Schultz [mailto:ch...@christopherschultz.net] Sent: Thursday, October 01, 2009 8:43 AM To: Tomcat Users List Subject: Re: Cannot set remote address in valve (Tomcat 5.5) -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Elli, On 9/27/2009 12:19 AM, Elli Albek wrote: public void setRemoteAddr(String remoteAddr) { // Not used } The variable is protected so I cannot access it directly from my code. What variable? The remoteAddress member? Is there any way to implement this Valve? Wrap the request object in a subclass that you write. This will allow you to either a) Override the setRemoteAddress method to return whatever you want b) Explicitly set the remoteAddress member to whatever you want - -chris -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.9 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkrEzh0ACgkQ9CaO5/Lv0PAmqwCeJpvyj0k9Ze+QKLkyRNqfpvzp nccAniLAI/gdF65qw9EF6HLsXqcSgacP =S2JM -END PGP SIGNATURE- - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
RE: Cannot set remote address in valve (Tomcat 5.5)
A few reasons why not to do this as a servlet filter: 1. There are many web apps on the server and I don't want to include the filter in each. 2. There are other valves like request filters that cannot work without the correct IP, as well as custom login valve. 3. We have a few environments and I don't want to have different war configurations for each. We had servers with and without load balancers and I can see that change again in the near future. This should not affect the application configuration. 4. It is logically part of the server environment and not part of the web application. The web application should not change based on the network architecture. If the system admin adds/removes the load balancer then he should know about one thing he needs to change in tomcat, and not rebuild all the wars without a filter. Network configuration should not require code rebuild with/without filters (we have to do a build to create war, like most people). E -- What about just implementing this as a filter and then construct a request wrapper in the filter to read that header and override the getRemoteAddr() method. --David - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Cannot set remote address in valve (Tomcat 5.5)
Thanks for the response. Is there any problem in fixing this method to actually set the variable (which is already in the class)? I think the set methods should actually set the values, so others can write such extensions without putting their code in the apache packages. Right now I guess the only thing I can do is to either use the valve class referenced in this bug report or put my class in an apache package, which I don't think it belongs to. I see that the class you pointed to is also in an apache package just for that reason. E - Original Message - From: Mark Thomas ma...@apache.org To: Tomcat Users List users@tomcat.apache.org Sent: Sun, 27 Sep 2009 02:13:49 -0700 (PDT) Subject: Re: Cannot set remote address in valve (Tomcat 5.5) https://issues.apache.org/bugzilla/show_bug.cgi?id=47330 is on the todo list but my current plan is to implement it as a Filter rather than a valve. What is the issue with using a Filter? If you really want to write a filter than that bug report should be all you need. Mark - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Cannot set remote address in valve (Tomcat 5.5)
Hi, We have Tomcat behind a load balancer. The servlet API and tomcat libraries see the load balancer IP as the client IP. I tried to write a simple valve which will extract the IP from HTTP header X-Forwarded-For and continue the valve chain using this IP as the client IP. This will be the first valve in the chain, so everything will work as normal afterwards including log files, IP filter valve, etc. The problem I am facing, is when I try to set the remote IP on the request from my valve, the code does nothing. This is the set method in the class org.apache.catalina.connector.Request: public void setRemoteAddr(String remoteAddr) { // Not used } The variable is protected so I cannot access it directly from my code. Is there any way to implement this Valve? Is there anything already shipped in tomcat to extract the client IP from the header? I DO NOT want to write a servlet filter for various reasons, so I hope there is a way to do it with a valve. Any help appreciated. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org