Re: [Resin-interest] More on include()/forward() issue.

2008-03-11 Thread Ilya Kasnacheev
В сообщении от 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.

2008-03-07 Thread Ilya Kasnacheev
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.

2008-03-07 Thread Ilya Kasnacheev
В сообщении от 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.

2008-03-07 Thread Ilya Kasnacheev
В сообщении от 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()

2008-02-28 Thread Ilya Kasnacheev
В сообщении от 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()

2008-02-27 Thread Ilya Kasnacheev
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

2008-01-17 Thread Ilya Kasnacheev
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