Re: [Resin-interest] More on include()/forward() issue.
В сообщении от 7 Март 2008 22:12 Mattias Jiderhamn написал(a): page - include (forward - forward - forward - forward - page) ... forward() in included servlet does not mean instead of including page but instead of included page Ok, now I see where you're coming from. Do you have to issue the explicit .flush() No I don't, but it eventually commits when enough data is printed to out. or would increasing the buffer (response.setBufferSize()) prevent the response from being comitted until the included forward has been issued??? This way is too like hack. What if we'll fill this buffer prematurely anyway? What about my anonymous wrapper? See reply to original post. It may work if you are certain there will be no flushing to the client before a forward(). Nope, there would be a lot of flushing before forward(). Because, forward() final destination isn't going to print page from scratch. Instead it is going to print a fragment of page to be include()d. After it will return, the rest of page() will be printed. Also, there can be quite a few such (include() - forward() - forward() - print()) sessions. Using a buffered dispatch-response is safer. I think I have an implementation lying around on my other computer which I could post, but you should also be able to easily implement it yourself or find it on the net. Yes, I understand, but for now I've just hacked isCommitted(). I'll know what to do if it'll stop working. ___ resin-interest mailing list resin-interest@caucho.com http://maillist.caucho.com/mailman/listinfo/resin-interest
[Resin-interest] More on include()/forward() issue.
Let's say we've got a servlet such as == protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { RequestDispatcher rd = getServletContext().getRequestDispatcher(/target); String s; s = Launcher: response is + response.getClass().getName() + (response.isCommitted() ? , commited : ); System.err.println(s); response.setContentType(text/plain; charset=koi8-r); PrintWriter out = response.getWriter(); s = Launcher: response is + response.getClass().getName() + (response.isCommitted() ? , commited : ); out.println(s); System.err.println(s); rd.include(request, response); out.flush(); s = Launcher: response is + response.getClass().getName() + (response.isCommitted() ? , commited : ); out.println(s); System.err.println(s); rd.include(request, response); s = Launcher: response is + response.getClass().getName() + (response.isCommitted() ? , commited : ); out.println(s); System.err.println(s); out.flush(); } == Let's say we have another servlet such as == protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String s; s = Target: response is + response.getClass().getName() + (response.isCommitted() ? , commited : ); System.err.println(s); response.setContentType(text/plain; charset=koi8-r); PrintWriter out = response.getWriter(); s = Target: response is + response.getClass().getName() + (response.isCommitted() ? , commited : ); System.err.println(s); out.println(s); out.flush(); s = Target: response is + response.getClass().getName() + (response.isCommitted() ? , commited : ); out.println(s); System.err.println(s); } == Let's say we map them to '/launcher' and '/target'. Let's say we call target on resin, we will get this on stderr: == Launcher: response is com.caucho.server.http.HttpResponse Launcher: response is com.caucho.server.http.HttpResponse Target: response is com.caucho.server.webapp.DispatchResponse Target: response is com.caucho.server.webapp.DispatchResponse Target: response is com.caucho.server.webapp.DispatchResponse, commited Launcher: response is com.caucho.server.http.HttpResponse, commited Target: response is com.caucho.server.webapp.DispatchResponse, commited Target: response is com.caucho.server.webapp.DispatchResponse, commited Target: response is com.caucho.server.webapp.DispatchResponse, commited Launcher: response is com.caucho.server.http.HttpResponse, commited == You see? DispatchResponse isComitted() always on the second run. Before Target did anything with that response. I don't think that's correct because it guaranties that some servlets will break. Like those who use forward(). I'll investigate that case further. Is there anything in J2EE docs to cover up current behavior? ___ resin-interest mailing list resin-interest@caucho.com http://maillist.caucho.com/mailman/listinfo/resin-interest
Re: [Resin-interest] More on include()/forward() issue.
В сообщении от 7 Март 2008 13:14 Ilya Kasnacheev написал(a): response P.S. I wonder how bad it can be: response = new HttpServletResponseWrapper(response) { public boolean isCommitted() { return false; } }; That's, like, http://folk.poesie.ru/files/private/ilyak/45218782.jpg P.P.S. Interesting enough, it actually works. Going to give it a try. ___ resin-interest mailing list resin-interest@caucho.com http://maillist.caucho.com/mailman/listinfo/resin-interest
Re: [Resin-interest] More on include()/forward() issue.
В сообщении от 7 Март 2008 15:48 Mattias Jiderhamn написал(a): If I understand your question: the reason the DispatchResponse is committed is that you have called .flush() explicitly on the original HttpServletRequest (HttpResponse). Yeah, that's what I did exactly. It would have committed it even if I didn't, provided I print enough text into out. This is nothing strange. Why could you want to create a wrapper to hide the commited state, so that you can perform forward??? forward means instead of include means also Well, the problem is that: include is like page - include page but including struts1 action is like page - include (forward - forward - forward - forward - page) The problem is that resin would not let me to forward, normally, when I include() such chain and buffer is already committed. This is wrong for two reasons: first, forward() in included servlet does not mean instead of including page but instead of included page, and second, inclue()ing document should I guess yield same result as fetching it via HTTP and then pasting. You cannot first generate or include content, flush it to the client (sent over the network to the web browser) and then say Oh wait, I changed my mind, I want to send this content instead (=forward). Nope. I've changed my mind inside included document, I want to send different content *to be included*. In fact, included document should have own distinct stream which itself might be committed or not, can be reset and so on.. Resin cheats this for speed and thus have only one stream for both main and included documents. But that breaks struts. If your design requires that the response is not commited, there is something wrong with your desing. Sorry, can't do anything with that. Need to do actual work instead of rewriting struts. An alternative approach, if for some reason you must do it this way, is to create wrapper classes that put the included content in a buffer (think ByteArrayOutputStream) until you are sure you want to send it to the client, then you write the buffer to the actual response. What about my anonymous wrapper? See reply to original post. ___ resin-interest mailing list resin-interest@caucho.com http://maillist.caucho.com/mailman/listinfo/resin-interest
Re: [Resin-interest] Resin 3.1, RequestDispatcher, include() and forward()
В сообщении от 27 Февраль 2008 19:30 Huitang Li написал(a): I tested with struts 1.0.x, 1.1.x, and 1.2.x, I got the same error. However, when I tried struts 1.3.8, this exception disappeared. Well, I've switched to struts 1.3.8 as you suggested, but exception is still in place. I guess I'll have to redesign my app a bit. ___ resin-interest mailing list resin-interest@caucho.com http://maillist.caucho.com/mailman/listinfo/resin-interest
[Resin-interest] Resin 3.1, RequestDispatcher, include() and forward()
I've found one thing in resin 3.1 regarding RequestDispatcher, include() and forward() Let's suppose we have a ServletResponse, and we've wrote some text into its output stream, so it's now in committed state. That means, as J2EE spec tells, that we can no longer do forward() on it, or we'll get an IllegalStateException. In the meantime we can do include() on it, including the response from random URI into result document. So we include() a chain of struts1 actions into it. They're going to forward() the request until the end of chain is reached. As I've found out, this will result in a shower of IllegalStateExceptions being thrown. Interesting thing that, despite those exceptions, actions successfully transfer control from one to another, eventually finishing processing and writing everything they need to. Now the weird thing is: On the first side, include()d document can be thought as being processed independently. Basically it should behave as if you fetched that page by using HTTP and then printed it into output stream. So, forward() should work because there is no reason for it to not work - because it would work in the case of outside request. On the second side, include()d document gets unmodified ServletResponse from parent servlet, which have its buffer committed, and I guess there are no easy ways to tell whenever forward() was called from include()d servlet, where it is fine, or from the parent servlet, where it's a no-no I can't say I have a question about resin, I just wanted to share that bunch of facts and thoughts with you. P.S. Having said that, I find the original limitation on forward() rather annoying. I guess it's supposed to ensure cookies and headers neither being written into document nor discarded, and also prevent from outputting half of one html document and then outputting the whole another html document. That's the well known We didn't want to let you shoot yourself in the foot so we duct taped your fingers together; and also, we wanted to prematurely optimise a bit antipattern clearly. ___ resin-interest mailing list resin-interest@caucho.com http://maillist.caucho.com/mailman/listinfo/resin-interest
[Resin-interest] Follow-up on my classloader recycle issue
Thanks for replies, Scott and Daniel! Today I went the 'find references and eliminate them' way. I looked into heap dump, found reference that could possibly screw things, and eliminated it. After each of them I started resin, touched web.xml for a few times and dumped heap. I've found this OQL query to be helpful, maybe someone else will need it someday: select map(filter(referrers(heap.findObject(0xsome ClassLoader ref)), it.name != null), heap.objects(it)) It lists all still-living class instances to classes loaded inside that classloader. More specifically, I've cleaned: - The only ThreadLocal we've got. - Properly closed Hibernate session - weird thing is that it did not led to dereferencing of that LanguageType objects. - Made two @attributes source-only - I'll have to revert that, but they were causing to those $ProxyXX instances floating around in soft references. - resin's SessionManager.close(): added _webApp = null; since I saw in dump SessionManagerAdmin was referencing SessionManager that referenced Application which was unable to garbage-collect and thus was holding classloader. Maybe I'm wrong here, but SessionManagerAdmin was referenced by those bean management services, and Application in question had a _sessionManager = null and still was referenced over that chain. - finally I've got rid of static ServletContext context; in one of classes. Theoretically, i think, it should be recycled because this dependency is circular: that class depends on ClassLoader, ClassLoader on Application, Application on that class. But practically, as I've found, I shouldn't do that :) After this, EnvironmentClassLoaders stopped spawning like crazy: if I run resin and touch web.xml for 10 times, I end up with four EnvorinmentClassLoader's for that web-app. That's still more than one, but here I think maybe JVM is just cleaning its garbage lazily: I've observed ClassLoader without Application in it, obviously it should be collected on the next run. - after that I've dropped two Application references in instance variables, with no noticeable difference. That list might seem lame in a sence 'he should have done all that long ago', but a few days ago I was all like 'a classloader? what's that?' - I knew theoretically that Classloaders exist and that garbage collector doesn't claim referenced objects, but I didn't think much about that, I didn't know that can cause problems. I'll now try to carefully revert some of those changes, and in future I'll care more about reference sanity. P.S. to Scott: I've looked at _scanListeners, but they're like 0 : [EMAIL PROTECTED] (64 bytes) 1 : [EMAIL PROTECTED] (113 bytes) 2 : null so I don't think they caused that problems. I think it was just my ignorance about static references being not necessarily good for one's health. ___ resin-interest mailing list resin-interest@caucho.com http://maillist.caucho.com/mailman/listinfo/resin-interest