Re: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-16 Thread Mark Thomas
On 15/03/2016 17:18, jimi.hulleg...@svensktnaringsliv.se wrote:
> On Friday, March 11, 2016 10:03 PM, ma...@apache.org wrote:
>>
>> Monday works. I might try experimenting with some ideas between now and then 
>> anyway.
> 
> Hi again,
> 
> A bit shorter reply this time, because of time shortage. I preferred to focus 
> the little time I managed to "break free" on testing the trunk version of 
> Tomcat 8 :)
> 
> And... it looks really great! I have performed some JMeter tests now, and 
> here are the results:
> 
> Tomcat 8.0.32
> Average 2500 ms per request.
> 
> Tomcat 8 trunk (revision 81735040)
> Average 360 ms per request
> 
> Tomcat 7.0.68
> Average 290 ms per request
> 
> 
> Test setup:
> - Windows 8
> - JMeter 2.13
> - Tomcat with a custom webapp, on Escenic CMS
> - JMeter running with one thread, and a throttle (Constant Throughput Timer) 
> set to 12 samples per minute (ie 5 seconds between each request)
> - Testing the start page (with lots of content)
> - Tomcat started fresh, and the webapp visited a few times in the browser as 
> a warmup
> - Waited until CPU fan and CPU load settled down before starting the test
> - No other traffic to Tomcat during the test
> - No resource hungry program running except Tomcat and JMeter
> 
> So, all in all, I see a huge improvement with our site. Going from 2500 ms to 
> 360 ms. :)
> As you can see, compared to Tomcat 7 it is still an increase with 70 ms, but 
> for our site that is not a "deal breaker".

Excellent. If need be, I think there is scope to improve that further
but if the results are good enough for you at this point, that work can
wait.

Mark


-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



RE: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-15 Thread jimi.hullegard
On Friday, March 11, 2016 10:03 PM, ma...@apache.org wrote:
> 
> Monday works. I might try experimenting with some ideas between now and then 
> anyway.

Hi again,

A bit shorter reply this time, because of time shortage. I preferred to focus 
the little time I managed to "break free" on testing the trunk version of 
Tomcat 8 :)

And... it looks really great! I have performed some JMeter tests now, and here 
are the results:

Tomcat 8.0.32
Average 2500 ms per request.

Tomcat 8 trunk (revision 81735040)
Average 360 ms per request

Tomcat 7.0.68
Average 290 ms per request


Test setup:
- Windows 8
- JMeter 2.13
- Tomcat with a custom webapp, on Escenic CMS
- JMeter running with one thread, and a throttle (Constant Throughput Timer) 
set to 12 samples per minute (ie 5 seconds between each request)
- Testing the start page (with lots of content)
- Tomcat started fresh, and the webapp visited a few times in the browser as a 
warmup
- Waited until CPU fan and CPU load settled down before starting the test
- No other traffic to Tomcat during the test
- No resource hungry program running except Tomcat and JMeter

So, all in all, I see a huge improvement with our site. Going from 2500 ms to 
360 ms. :)
As you can see, compared to Tomcat 7 it is still an increase with 70 ms, but 
for our site that is not a "deal breaker".

Regards
/Jimi

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: ***UNCHECKED*** RE: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-11 Thread Mark Thomas
On 11/03/2016 19:00, jimi.hulleg...@svensktnaringsliv.se wrote:
> On Friday, March 11, 2016 6:07 PM, ma...@apache.org wrote:



> I'm wasn't talking about gathering information regarding performance. I was 
> talking about gathering information about what jsp/tag code and what EL 
> variable names are responsible for this, and how often it happens. In order 
> to get a grasp of if it is feasible to solve by fixing the code. For example, 
> if this log output showed me that 90% of the ClassNotFoundExceptions happen 
> because of a handful of jsp/tag files, then I would just fix these and see 
> how much that helped. But if the log output would indicate that this problem 
> is spread out over too many jsp and tag files, then I wouldn't even try and 
> fix it in the code, but would instead try some other approach (like disabling 
> this feature, or reverting back to Tomcat 7).

Ah, now I understand your motivation. debug logging would be more
helpful than a profiler in that case.

The next problem is that we are in a spec class and can't add any
dependencies. That forces a hard dependency on java.util.logging which
isn't great.

What you can do is turn on debug logging for the web application class
loader. That should get you most of what you need.

>> At the point where you'd need to access the ServletContext to read the 
>> configuration, the ServletContext isn't available.
>> [...]
>> Since I wrote the "configuration API" above, I did some more research and 
>> found the route 
>> via the ELContext. That is what the implemented solution uses. 
> 
> So, just to check if I understood you correctly... You *can* get access to 
> the ServletContext, right? (Using page.getServletContext()...)

No, the ServletContext isn't directly accessible but more digging shows
some helpful signs.

ScopedAttributeELResolver can access the current JspContext. That has
access to the page/request/session/application attributes and can
probably be cast to PageContext which has access to the ServletContext.
So there is a (slightly contrived) route by which per web application
config can be passed without breaking the spec and per page config can
be passed with custom code or extending the spec (which as far as the
spec owners are concerned is the same thing as breaking the spec).

>> And why would it not work for some users? I'm not saying it would magically 
>> solve the problem for everyone. But it would solve the worst problems for 
>> most people, and it wouldn't make it worse for anyone (ie, the fact that one 
>> would have the *option* to turn it off, doesn't make the situation worse).
> 
> 
>> Which is my point. The solution doesn't help those users that need imports 
>> and 
>> good performance. Greater granularity in configuration helps to a point but 
>> there will be users that need imports and good performance on the same page 
>> and per expression configuration is taking things a bit too far for my taste.
> 
> I'm sorry, but I don't follow you now. Are you saying that since there are 
> people who wouldn't benefit from this (but not get hurt either), there is no 
> reason to fix it for those that *would* benefit from it?

I'm saying that I prefer to expend effort on a solution that doesn't
break the spec and works for everyone than one that only works for some
users, probably involves breaking the spec and increases configuration
complexity.

>> Per page is certainly better than global but I still have concerns. In 
>> addition to the large pages 
>> needing imports and performance above, I'm concerned that there is no good 
>> default for
>> an option that disables import support. Disabling imports by default will 
>> break pages that 
>> use imports unless the developer adds the extra code. Not disabling them by 
>> default means 
>> having to add code to every page with a performance problem.
> 
> Well, I never said that it would solve the problem for everyone. But for 
> people who don't use any EL imports at all (like everyone migrating from 
> Tomcat 7), they would benefit from a global *off* option, and then they can 
> systematically enable this feature slowly, page by page, as they add 
> functionality that depends on it.

Page by page config requires breaking the spec which at this point I'd
rather not do by default.

> As for people who have pages that need both imports and performance, I still 
> claim that this fix wouldn't make it any *worse* for them. In fact, I would 
> claim that it would make it somewhat better, because now they would have an 
> option to control what pages should have this feature, and if they have 
> important pages that doesn't use imports then they at least could reduce the 
> performance problem for those pages. And regarding the pages with both a need 
> for both imports and performance, well they still have the workaround that 
> was mentioned in the beginning of this thread, adding a specific scope to all 
> the EL variables (at least the ones that can be null or not set).

RE: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-11 Thread jimi.hullegard
On Friday, March 11, 2016 6:07 PM, ma...@apache.org wrote:
> 
> And a debug log message is unlikely to tell you any more than the thread dump 
> did. 

That depends on what is actually being logged. If the class name is printed, 
then one could immediately figure out the name of the EL variable (like 
"java.lang.myTempValue", then the EL parameter name is "myTempValue").

And the thread dump only gives me a snapshot, containing 0, 1 or more 
stacktraces with the ClassNotFoundException. Unless I take a threaddump every 
millisecond (or even more often), the thread dump method would miss some 
stacktraces. With logging, it would not miss any.


> If the same code keeps appearing in a thread dump it is a fair bet that time 
> is being spent in that code but you still need performance data - which you 
> can't get from debug logging or thread dumps - to be certain.

I'm wasn't talking about gathering information regarding performance. I was 
talking about gathering information about what jsp/tag code and what EL 
variable names are responsible for this, and how often it happens. In order to 
get a grasp of if it is feasible to solve by fixing the code. For example, if 
this log output showed me that 90% of the ClassNotFoundExceptions happen 
because of a handful of jsp/tag files, then I would just fix these and see how 
much that helped. But if the log output would indicate that this problem is 
spread out over too many jsp and tag files, then I wouldn't even try and fix it 
in the code, but would instead try some other approach (like disabling this 
feature, or reverting back to Tomcat 7).



> As for using it in production, you aren't going to be using a profiler unless 
> you have a problem. 
> I'd look at the risk (never seen an issue) of using a profiler against the 
> production system and 
> the quality of data / time to useful results vs debug logging and the longer 
> to get results / lower 
> quality of data and choose the profiler every time. YMMV.

Well, I guess you have a point. But the fact is that we don't have any profiler 
tool installed in production right now (and I suspect that is a quite common 
scenario for many users in general), and having one installed is not something 
that is done quickly. Enabling trace or debug logging in a specific class takes 
less than a minute, giving me much needed information more or less instantly.

But yes, if one would have followed common sense, and already had a profiler 
installed (and have used it enough to know how to get it to output the needed 
information), then you would be right ;)



> At the point where you'd need to access the ServletContext to read the 
> configuration, the ServletContext isn't available.
> [...]
> Since I wrote the "configuration API" above, I did some more research and 
> found the route 
> via the ELContext. That is what the implemented solution uses. 

So, just to check if I understood you correctly... You *can* get access to the 
ServletContext, right? (Using page.getServletContext()...)



> It should be possible to hook up your proposed configuration option 
> to pass data via that as long as the code is careful.

OK. Sounds promising. Fingers crossed. :)


> And why would it not work for some users? I'm not saying it would magically 
> solve the problem for everyone. But it would solve the worst problems for 
> most people, and it wouldn't make it worse for anyone (ie, the fact that one 
> would have the *option* to turn it off, doesn't make the situation worse).


> Which is my point. The solution doesn't help those users that need imports 
> and 
> good performance. Greater granularity in configuration helps to a point but 
> there will be users that need imports and good performance on the same page 
> and per expression configuration is taking things a bit too far for my taste.

I'm sorry, but I don't follow you now. Are you saying that since there are 
people who wouldn't benefit from this (but not get hurt either), there is no 
reason to fix it for those that *would* benefit from it?



> Per page is certainly better than global but I still have concerns. In 
> addition to the large pages 
> needing imports and performance above, I'm concerned that there is no good 
> default for
> an option that disables import support. Disabling imports by default will 
> break pages that 
> use imports unless the developer adds the extra code. Not disabling them by 
> default means 
> having to add code to every page with a performance problem.

Well, I never said that it would solve the problem for everyone. But for people 
who don't use any EL imports at all (like everyone migrating from Tomcat 7), 
they would benefit from a global *off* option, and then they can systematically 
enable this feature slowly, page by page, as they add functionality that 
depends on it.

As for people who have pages that need both imports and performance, I still 
claim that this fix wouldn't make it any *worse* for them. In fact, I would 

Re: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-11 Thread Mark Thomas
On 11/03/2016 14:17, jimi.hulleg...@svensktnaringsliv.se wrote:
> On Thursday, March 10, 2016 10:44 PM, ma...@apache.org wrote:
>>
>> We'll have to agree to disagree on that one. If you are concerned
>> about a performance issue then you need to know where to look to
>> enable debug logging. A profiler will tell you where to look and
>> at that point you don't need the debug logging.
> 
> Well, first of all, I found this without knowing where to look. I just 
> checked the thread dump, looked closer at the stack traces involving the 
> ClassNotFoundExceptions, and found the try catch clause. If there would have 
> been a log.debug(...) or log.trace(...) statement there, then I would know 
> how to enable debug logging for this. All without knowing beforehand where to 
> look, and all without anybody telling me where to look.

And a debug log message is unlikely to tell you any more than the thread
dump did. If the same code keeps appearing in a thread dump it is a fair
bet that time is being spent in that code but you still need performance
data - which you can't get from debug logging or thread dumps - to be
certain.

> Secondly, not all problems are easily reproducible in a 
> development/test/staging environment, especially if one depends on the nature 
> of the production traffic to find all (or at least most) places in the code 
> that experience problems. Not all organizations have the time and/or the 
> money to replay/simulate live traffic in another environment. And I suspect 
> that most IT departments and/or service providers would react with some 
> suspicion or worry if one would try and get them to introduce a profiler in 
> production, even though these tools have become more and more production 
> friendly over the years.

You still need to know what debug logging to turn on and if you are
guessing based on thread dumps then you already have everything debug
logging is likely to give you.

> Thirdly, even if profiling would be an option, if no profiling is setup 
> already then it would take some time and money to do that. Compared to the 
> trivial change of logging level for a specific class. And I can't really see 
> how log.debug(...) or log.trace(...)  (possibly surrounded by a 
> log.isDebugEnabled() or isTraceEnabled())would have any negative effect for 
> anyone.

Compared to the cost of the time to debug issues without a profiler, the
cost of a profiler is tiny. I use YourKit (because they give me a free
copy to use for my ASF work) and, while the price of it has gone up
quite a bit since I last looked a few years ago, it still (in my view)
offers a very quick return on investment.

As for using it in production, you aren't going to be using a profiler
unless you have a problem. I'd look at the risk (never seen an issue) of
using a profiler against the production system and the quality of data /
time to useful results vs debug logging and the longer to get results /
lower quality of data and choose the profiler every time. YMMV.

>> The code in question is in the JSP API JAR and there is no 
>> configuration API available. The only option would be 
>> a system property which would make it a global configuration option.
> 
> I'm not sure I understand why the absence of a "configuration API" would stop 
> you from simply checking for a specific init parameter in the servlet context 
> (thus making it possible to configure it in the web.xml using a 
> context-param). And when it comes to per jsp configuration, one could check 
> for a page scoped attribute with the same name. Ideally this could be added 
> as a new page directive attribute (like <%@ page disableELImports="true" %>), 
> but I guess that would constitute a "configuration API" change that would 
> have to be in the specification. But the init parameter or page scoped 
> attribute could be fine interim solutions, until the specification is updated 
> to add these configuration options the proper way.

At the point where you'd need to access the ServletContext to read the
configuration, the ServletContext isn't available. The code in question
is in a spec JAR and we can't change the public API in any way, nor can
we add a dependency to some other component. That tends to leave system
properties as the only option.

Since I wrote the "configuration API" above, I did some more research
and found the route via the ELContext. That is what the implemented
solution uses. It should be possible to hook up your proposed
configuration option to pass data via that as long as the code is careful.

> And why would it not work for some users? I'm not saying it would magically 
> solve the problem for everyone. But it would solve the worst problems for 
> most people, and it wouldn't make it worse for anyone (ie, the fact that one 
> would have the *option* to turn it off, doesn't make the situation worse).

Which is my point. The solution doesn't help those users that need
imports and good performance. Greater granularity in 

RE: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-11 Thread jimi.hullegard
On Thursday, March 10, 2016 10:44 PM, ma...@apache.org wrote:
> 
> We'll have to agree to disagree on that one. If you are concerned
> about a performance issue then you need to know where to look to
> enable debug logging. A profiler will tell you where to look and
> at that point you don't need the debug logging.

Well, first of all, I found this without knowing where to look. I just checked 
the thread dump, looked closer at the stack traces involving the 
ClassNotFoundExceptions, and found the try catch clause. If there would have 
been a log.debug(...) or log.trace(...) statement there, then I would know how 
to enable debug logging for this. All without knowing beforehand where to look, 
and all without anybody telling me where to look.

Secondly, not all problems are easily reproducible in a 
development/test/staging environment, especially if one depends on the nature 
of the production traffic to find all (or at least most) places in the code 
that experience problems. Not all organizations have the time and/or the money 
to replay/simulate live traffic in another environment. And I suspect that most 
IT departments and/or service providers would react with some suspicion or 
worry if one would try and get them to introduce a profiler in production, even 
though these tools have become more and more production friendly over the years.

Thirdly, even if profiling would be an option, if no profiling is setup already 
then it would take some time and money to do that. Compared to the trivial 
change of logging level for a specific class. And I can't really see how 
log.debug(...) or log.trace(...)  (possibly surrounded by a 
log.isDebugEnabled() or isTraceEnabled())would have any negative effect for 
anyone.

Just my two cents...


> The code in question is in the JSP API JAR and there is no 
> configuration API available. The only option would be 
> a system property which would make it a global configuration option.

I'm not sure I understand why the absence of a "configuration API" would stop 
you from simply checking for a specific init parameter in the servlet context 
(thus making it possible to configure it in the web.xml using a context-param). 
And when it comes to per jsp configuration, one could check for a page scoped 
attribute with the same name. Ideally this could be added as a new page 
directive attribute (like <%@ page disableELImports="true" %>), but I guess 
that would constitute a "configuration API" change that would have to be in the 
specification. But the init parameter or page scoped attribute could be fine 
interim solutions, until the specification is updated to add these 
configuration options the proper way.



> Um, no. See above. This would have to be a global option. It would work for 
> some users/pages but not for others.

Um, yes, see above. ;)

And why would it not work for some users? I'm not saying it would magically 
solve the problem for everyone. But it would solve the worst problems for most 
people, and it wouldn't make it worse for anyone (ie, the fact that one would 
have the *option* to turn it off, doesn't make the situation worse).


> Generally, the suggestions are reasonable. The control can't be as 
> fine-grained as you suggest but that isn't necessarily a show-stopper.

Well, the solution with the page scoped attribute in the jsp page would make it 
fine grained enough for most people, don't you think? :)

I would also be interested in hearing your thoughts about having an option to 
disable this class lookup for all names that doesn't start with a capital 
letter. Thus making ${Boolean.TRUE} work as normal, while skipping ${foo.bar}, 
even if they coexist in the same jsp page. I actually would think that would be 
the best solution to this, since the naming convention dictates that you should 
start class names with capital letter, and variables with lower case letters.

Basically, the code could look something like this, in 
ScopedAttributeELResolver.java:

if (importHandler != null) {
if (resolveClass) {
//disableELImportsForNamesNotStartingWithUpperCase is false by 
default,
//and can be configured using for example a web.xml init 
parameter
if (disableELImportsForNamesNotStartingWithUpperCase && 
!Character.isUpperCase(key.charAt(0))) {
resolveClass = false;
}
}
if (resolveClass) {
...
}
...



> The main disadvantage that these options have is that a 
> better solution is available. Follow the bug report from 
> my previous message in this thread for details.
> [...]
> In this case, I believe the root cause has been fixed.

That sounds great! And I saw now in the bug report page that your simple test 
case indicated a ~1ms performance gain per avoided ClassNotFoundException. That 
sounds very close to my own tests, where the start page takes about 2500 ms, 
and I counted about 2700 ClassNotFoundExceptions.


Re: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-11 Thread Mark Thomas
On 10/03/2016 22:16, Christopher Schultz wrote:
> Mark,
> 
> On 3/10/16 4:43 PM, Mark Thomas wrote:
>> On 10/03/2016 21:16, jimi.hulleg...@svensktnaringsliv.se wrote:
>>> On Thursday, March 10, 2016 11:20 AM, ma...@apache.org wrote:

> 3. Why is the problem not limited to the first request for a
> jsp page?

 Because EL imports may be dynamic so the EL has to be evaluated
 on execution.
>>>
>>> I'm not really sure I follow you now. Can you explain what you
>>> mean with dynamic imports in this regard? I can't see any
>>> mentioning of it in the specs 
>>> (http://download.oracle.com/otn-pub/jcp/el-3_0-fr-eval-spec/EL3.0.FR.
> pdf).
> 
>>>
>> There is nothing stopping a JSP author obtaining a reference to
>> the ImportHandler and conditionally adding classes to import. The 
>> configuration of the ImportHandler could change on every call to
>> the page.
> 
> What about marking the ImportHandler as "dirty" and flushing a cache
> of prior lookups? (Or are we talking about spec-defined classes only,
> here?)

We are talking about spec defined classes here.

Also, ELContext and ImportHandler are not cached across requests and a
class level cache doesn't work because each page can have different imports.

I looked at caching when this issue first arose and we already cache
everything we can. Fixing the performance issue required a different
approach based on making the affected Resolver more aware of the context
in which it was being used so it could skip the ImportHandler in the
affected cases.

Mark

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-10 Thread Christopher Schultz
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Mark,

On 3/10/16 4:43 PM, Mark Thomas wrote:
> On 10/03/2016 21:16, jimi.hulleg...@svensktnaringsliv.se wrote:
>> On Thursday, March 10, 2016 11:20 AM, ma...@apache.org wrote:
>>> 
 3. Why is the problem not limited to the first request for a
 jsp page?
>>> 
>>> Because EL imports may be dynamic so the EL has to be evaluated
>>> on execution.
>> 
>> I'm not really sure I follow you now. Can you explain what you
>> mean with dynamic imports in this regard? I can't see any
>> mentioning of it in the specs 
>> (http://download.oracle.com/otn-pub/jcp/el-3_0-fr-eval-spec/EL3.0.FR.
pdf).
>
>> 
> There is nothing stopping a JSP author obtaining a reference to
> the ImportHandler and conditionally adding classes to import. The 
> configuration of the ImportHandler could change on every call to
> the page.

What about marking the ImportHandler as "dirty" and flushing a cache
of prior lookups? (Or are we talking about spec-defined classes only,
here?)

- -chris
-BEGIN PGP SIGNATURE-
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iEYEARECAAYFAlbh8j4ACgkQ9CaO5/Lv0PDP1gCgtBnEJJA9er6w5mC1MUCLofA+
qqYAn2tBNbTYYL+fuV1rIEOklNlPOfsG
=vsTe
-END PGP SIGNATURE-

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-10 Thread Mark Thomas
On 10/03/2016 21:16, jimi.hulleg...@svensktnaringsliv.se wrote:
> On Thursday, March 10, 2016 11:20 AM, ma...@apache.org wrote:
>> 
>>> 3. Why is the problem not limited to the first request for a jsp
>>> page?
>> 
>> Because EL imports may be dynamic so the EL has to be evaluated on
>> execution.
> 
> I'm not really sure I follow you now. Can you explain what you mean
> with dynamic imports in this regard? I can't see any mentioning of it
> in the specs
> (http://download.oracle.com/otn-pub/jcp/el-3_0-fr-eval-spec/EL3.0.FR.pdf).

There is nothing stopping a JSP author obtaining a reference to the
ImportHandler and conditionally adding classes to import. The
configuration of the ImportHandler could change on every call to the page.

>  Can you give a concrete example, where an EL expression element
> would need to be evaluated as a potential class, again and again for
> each request?

See above.

> Because the way I see it, "foo" in ${foo.bar} in some jsp page only
> needs to be evaluated once. If "foo" corresponded to a class,
> matching one of the imports in the jsp, then this lookup will not
> change unless the jsp code changes. And the same is true if the
> lookup failes with a ClassNotFoundException. What am I missing?

See above.

>>> 4. Why isn't the ClassNotFoundException logged by the
>>> ImportHandler?
>> 
>> Because it is expected and logging it provides no value to the
>> user.
> 
> Well, I happen to disagree. :) In our case, if we could see all these
> stacktraces in the log, by enabling DEBUG/TRACE log level on the
> ImportHandler class for example, then we would quickly see just how
> big this problem is (ie how often this happens), on what jsp pages it
> happens, and what EL expressions cause it.

We'll have to agree to disagree on that one. If you are concerned about
a performance issue then you need to know where to look to enable debug
logging. A profiler will tell you where to look and at that point you
don't need the debug logging.

> On my local machine, I was able to "catch" the ClassNotFoundException
> using a debug breakpoint in my IDE, and using the breakpoint hit
> count I could see that this exception is thrown and handled (ie
> ignored) by the ImportHandler 2700 times for a single request to the
> start page.
> 
> 
>> The JavaEE specs are very big on backwards compatibility. 
>> Therefore, the chances of changing the spec syntax to fix this are
>> zero.
> 
> OK. Fair enough. I agree with you that backwards compatibility is
> important. But there are ways to fix this while still keeping the
> backwards compatibility. For example by making it possible to turn
> off this feature (globally, per webapp, or per jsp), where the
> default is "on". Wouldn't you agree that such a change would be 100%
> backwards compatible?

The code in question is in the JSP API JAR and there is no configuration
API available. The only option would be a system property which would
make it a global configuration option.

> And at the same time it would more or less
> solve this problem completely. Because people who experience the
> mentioned problems could turn of this setting globally, and then only
> enable it for those specific jsp pages where it is needed (and these
> pages would then be cleaned up, so that no EL-references exist
> without specific scope unless they are known to never be null. Tada,
> problem solved! =)

Um, no. See above. This would have to be a global option. It would work
for some users/pages but not for others.

> Actually... this wouldn't even need to be in the specifications... I
> can't see any harm in a EL implementation introducing such settings
> on its own, before the specifications can "catch up". That way you
> could basically introduce this fix in trunk right now, and have it
> tested and out in a stable release in no time =)

We have added such spec breaking options in the past as you'll see if
you look at the configuration docs for system properties. Generally, I'm
not a fan of configuration via system property. It is usually too blunt
a tool and doesn't provide the per webapp control that most users need.

> On Thursday, March 10, 2016 1:24 PM, ma...@apache.org wrote:
>> 
>> The issue is in ScopedAttributeELResolver.
>> 
>> ScopedAttributeELResolver checks the
>> page/request/session/application context first and only if it
>> doesn't find the attribute there does it try loading the class.
> 
> When debugging this in my IDE, I could see this in action. I also
> noticed that the ImportHandler that performs the class lookup is
> fetched from the ELContext object. So if I could wrap that object, I
> could simply return null in the method getImportHandler(), thus
> disabling this functionallity and therefore solving the performance
> problem for us. But I couldn't find any way to wrap the ELContext,
> for some reason. Can it be done, using standard code or config?

No.

> Or can this "import logic" be disabled some other way?

You can do most things via reflection, 

RE: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-10 Thread jimi.hullegard
On Thursday, March 10, 2016 11:20 AM, ma...@apache.org wrote:
> 
> > 3. Why is the problem not limited to the first request for a jsp page? 
> 
> Because EL imports may be dynamic so the EL has to be evaluated on execution.

I'm not really sure I follow you now. Can you explain what you mean with 
dynamic imports in this regard? I can't see any mentioning of it in the specs 
(http://download.oracle.com/otn-pub/jcp/el-3_0-fr-eval-spec/EL3.0.FR.pdf).

Can you give a concrete example, where an EL expression element would need to 
be evaluated as a potential class, again and again for each request?

Because the way I see it, "foo" in ${foo.bar} in some jsp page only needs to be 
evaluated once. If "foo" corresponded to a class, matching one of the imports 
in the jsp, then this lookup will not change unless the jsp code changes. And 
the same is true if the lookup failes with a ClassNotFoundException. What am I 
missing?


> > 4. Why isn't the ClassNotFoundException logged by the ImportHandler?
> 
> Because it is expected and logging it provides no value to the user.

Well, I happen to disagree. :)
In our case, if we could see all these stacktraces in the log, by enabling 
DEBUG/TRACE log level on the ImportHandler class for example, then we would 
quickly see just how big this problem is (ie how often this happens), on what 
jsp pages it happens, and what EL expressions cause it.

On my local machine, I was able to "catch" the ClassNotFoundException using a 
debug breakpoint in my IDE, and using the breakpoint hit count I could see that 
this exception is thrown and handled (ie ignored) by the ImportHandler 2700 
times for a single request to the start page. 


> The JavaEE specs are very big on backwards compatibility. 
> Therefore, the chances of changing the spec syntax to fix this are zero.

OK. Fair enough. I agree with you that backwards compatibility is important. 
But there are ways to fix this while still keeping the backwards compatibility. 
For example by making it possible to turn off this feature (globally, per 
webapp, or per jsp), where the default is "on". Wouldn't you agree that such a 
change would be 100% backwards compatible? And at the same time it would more 
or less solve this problem completely. Because people who experience the 
mentioned problems could turn of this setting globally, and then only enable it 
for those specific jsp pages where it is needed (and these pages would then be 
cleaned up, so that no EL-references exist without specific scope unless they 
are known to never be null. Tada, problem solved! =)

Actually... this wouldn't even need to be in the specifications... I can't see 
any harm in a EL implementation introducing such settings on its own, before 
the specifications can "catch up". That way you could basically introduce this 
fix in trunk right now, and have it tested and out in a stable release in no 
time =)



On Thursday, March 10, 2016 1:24 PM, ma...@apache.org wrote:
> 
> The issue is in ScopedAttributeELResolver.
> 
> ScopedAttributeELResolver checks the page/request/session/application context
> first and only if it doesn't find the attribute there does it try loading the 
> class.

When debugging this in my IDE, I could see this in action. I also noticed that 
the ImportHandler that performs the class lookup is fetched from the ELContext 
object. So if I could wrap that object, I could simply return null in the 
method getImportHandler(), thus disabling this functionallity and therefore 
solving the performance problem for us. But I couldn't find any way to wrap the 
ELContext, for some reason. Can it be done, using standard code or config? Or 
can this "import logic" be disabled some other way?

There really should be a way for users to disable this, if the functionallity 
is not used and it just is causing problems. And, like I said above, that could 
be done without breaking the specs. And an alternative way to the way above, 
could be like I mentioned before, to add a configuration option that forces the 
class name to begin with a capital letter. That way ${Boolean.TRUE}, 
${Integer.MAX_VALUE} and ${MyClass.myStaticField} would still work, while 
${foo.bar} etc would simply be ignored. As long as the configuration option 
would default to false (ie lower case first letter is allowed, as per the 
specification) it wouldn't break the specification unless the user deliberately 
told it to (which is fine, right?).

It would be really nice to get your input on these suggestions. And if you 
don't like them, could you explain why? If your opinion is "We need to stick 
100% to the specification, and never ever give even the expert user any way to 
override this, ever", then I would say that such a view causes more harm than 
good. :)

Regards
/Jimi

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-10 Thread Mark Thomas
On 10/03/2016 10:19, Mark Thomas wrote:
> On 10/03/2016 08:12, jimi.hulleg...@svensktnaringsliv.se wrote:



>> Then surely one can look at the other implementations, and what they did to 
>> avoid this problem. But one thing off the top of my head would be to at 
>> least avoid doing that class lookup in cases where it couldn't be a static 
>> field reference (like ${name}, since there is no dot after "name", there is 
>> no reason to check if "name" is a class reference, right?).
> 
> It has been a while since I looked at this. I need to remind myself why
> I thought it needed to be implemented this way. I recall looking at this
> at least once before but another look wouldn't hurt.

Having reviewed this, here is some useful background.

The issue is in ScopedAttributeELResolver.

ScopedAttributeELResolver checks the page/request/session/application
context first and only if it doesn't find the attribute there does it
try loading the class.

If ScopedAttributeELResolver is asked to resolve "foo" it can't
differentiate between ${ foo } which doesn't require a class lookup and
${ foo.bar } which does require a class lookup. Therefore
ScopedAttributeELResolver will always do a class lookup if it didn't
find an a matching attribute.

These lookups pass through various standard APIs (EL and JSP specs) so
we can't simply add a flag to the method to indicate if a class lookup
is required or not.

We can't use ThreadLocals because either:
- the ThreadLocal would need to be defined in a specification class
  which isn't allowed because we can't change the public API; or
- the ThreadLocal would need to be defined in Tomcat and referenced in
  a spec class which isn't allowed because the spec JARs have to be
  independent.

However, all is not lost. I think I have a solution based on ELContext
getContext()/putContext(). Keep an eye on
https://bz.apache.org/bugzilla/show_bug.cgi?id=57583 for progress reports.

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-10 Thread Mark Thomas
On 10/03/2016 08:12, jimi.hulleg...@svensktnaringsliv.se wrote:
> On Wednesday, March 9, 2016 8:22 PM, ma...@apache.org wrote:
>> It is a known 'feature' of the new EL requirements added in 3.0. The EL 
>> parser can't differentiate 
>> between an attribute without a scope and a reference to an static field.
>>
>> See https://bz.apache.org/bugzilla/show_bug.cgi?id=57583
> 
> Interesting. I can see how that in a way could explain the the performance 
> regression. But what I don't understand is:
> 
> 1. Why would this cause a ClassNotFoundException? What class exactly is it 
> trying to load?

For each imported package, it is trying to load package.attributeName

> 2. Why is this happening seemingly intermittently, with different EL 
> variables each time?

It isn't. It is happening every time. You are just observing it
intermittently. Probably because class loading is serial by default and
how observable this is depends on how many threads are trying to load
classes in parallel. Note that 9.0.x will use  ParallelWebappClassLoader
by default from the next release and you can always switch to that class
loader in 8.0.x

> 3. Why is the problem not limited to the first request for a jsp page? We see 
> this problem even days after a restart, for jsp-pages that definitely have 
> been used multiple times already, with the same state for it's variables.

Because EL imports may be dynamic so the EL has to be evaluated on
execution.

> 4. Why isn't the ClassNotFoundException logged by the ImportHandler?

Because it is expected and logging it provides no value to the user.

> 5. Why would this change between Tomcat 7 and Tomcat 8, with the exact same 
> webapp war with the exact same web.xml?

Because imports and statics were added in EL 3.0 which was first
implemented in Tomcat 8.

> 6. In our web.xml we specify version="2.5". Wouldn't that mean EL version 
> 2.1? (http://tomcat.apache.org/whichversion.html)

No. The version you specify in web.xml only determines the rules that
Tomcat uses to validate the web.xml. It has zero impact on the behaviour
of the container. The overall JavaEE EG made it very clear that this is
how they expected implementations to behave.

>> The way to avoid it is to always add an explicit scope (page, request, 
>> application, session) to your attributes.
> 
> Is this an official recommendation, stemming from the EL 3.0 specifications? 
> If so, can you point me to that paragraph in the specification document, or 
> some other paper of similar nature? Because when I look at the 3.0 
> specification document, all I see is examples without scope.
> 
> Or is this just a pragmatic response to the Tomcat/Jasper implementation of 
> the specifications?

It is the best recommendation I have right now based on what I know
about the EL spec and Tomcat's implementation of it.

> The reason I ask is that a simple search in our code base show that we have 
> about 10.000 potential candidates for the change you are suggesting, spread 
> out in hundreds of jsp files in our project. And on top of that, the CMS that 
> we use have their own jsp files, and a quick check indicates thousands of 
> potential candidates for the change there as well. So not only would we have 
> to perform a monumental task in our own code (because we would need to 
> determine the scope manually, for each and every variable), we also would 
> need to ask the CMS company to perform the same task.

You aren't the only one in that position.

>> Suggestions for improvements to the default ImportHandler implementation to 
>> make this faster are welcome.
> 
> Well, I am quite pragmatic in my thinking. Is this EL implementation the only 
> implementation with this problem?

I don't know. There aren't that many JSP implementations out there. The
end result should be the same with all of them but how they get there
may vary.

> Then surely one can look at the other implementations, and what they did to 
> avoid this problem. But one thing off the top of my head would be to at least 
> avoid doing that class lookup in cases where it couldn't be a static field 
> reference (like ${name}, since there is no dot after "name", there is no 
> reason to check if "name" is a class reference, right?).

It has been a while since I looked at this. I need to remind myself why
I thought it needed to be implemented this way. I recall looking at this
at least once before but another look wouldn't hurt.

> Otherwise, if more or less all implementations suffer from this problem, then 
> maybe it is the specification that is to blame. Maybe, when introducing the 
> new concept of EL references to static fields, they could use a special 
> prefix, like ${static.Boolean.True}, or they could have had this feature 
> turned off by default, with the possibility to turn it on either per jsp page 
> (using some page directive like <%@ page staticElReferences="true" %>) or 
> webapp-globally in the web.xml. Or, they could simply include the requirement 
> 

RE: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-10 Thread jimi.hullegard
On Wednesday, March 9, 2016 8:22 PM, ma...@apache.org wrote:
> It is a known 'feature' of the new EL requirements added in 3.0. The EL 
> parser can't differentiate 
> between an attribute without a scope and a reference to an static field.
> 
> See https://bz.apache.org/bugzilla/show_bug.cgi?id=57583

Interesting. I can see how that in a way could explain the the performance 
regression. But what I don't understand is:

1. Why would this cause a ClassNotFoundException? What class exactly is it 
trying to load?
2. Why is this happening seemingly intermittently, with different EL variables 
each time?
3. Why is the problem not limited to the first request for a jsp page? We see 
this problem even days after a restart, for jsp-pages that definitely have been 
used multiple times already, with the same state for it's variables.
4. Why isn't the ClassNotFoundException logged by the ImportHandler?
5. Why would this change between Tomcat 7 and Tomcat 8, with the exact same 
webapp war with the exact same web.xml?
6. In our web.xml we specify version="2.5". Wouldn't that mean EL version 2.1? 
(http://tomcat.apache.org/whichversion.html)

> The way to avoid it is to always add an explicit scope (page, request, 
> application, session) to your attributes.

Is this an official recommendation, stemming from the EL 3.0 specifications? If 
so, can you point me to that paragraph in the specification document, or some 
other paper of similar nature? Because when I look at the 3.0 specification 
document, all I see is examples without scope.

Or is this just a pragmatic response to the Tomcat/Jasper implementation of the 
specifications?

The reason I ask is that a simple search in our code base show that we have 
about 10.000 potential candidates for the change you are suggesting, spread out 
in hundreds of jsp files in our project. And on top of that, the CMS that we 
use have their own jsp files, and a quick check indicates thousands of 
potential candidates for the change there as well. So not only would we have to 
perform a monumental task in our own code (because we would need to determine 
the scope manually, for each and every variable), we also would need to ask the 
CMS company to perform the same task.

> Suggestions for improvements to the default ImportHandler implementation to 
> make this faster are welcome.

Well, I am quite pragmatic in my thinking. Is this EL implementation the only 
implementation with this problem? Then surely one can look at the other 
implementations, and what they did to avoid this problem. But one thing off the 
top of my head would be to atleast avoid doing that class lookup in cases where 
it couldn't be a static field reference (like ${name}, since there is no dot 
after "name", there is no reason to check if "name" is a class reference, 
right?). 

Otherwise, if more or less all implementations suffer from this problem, then 
maybe it is the specification that is to blame. Maybe, when introducing the new 
concept of EL references to static fields, they could use a special prefix, 
like ${static.Boolean.True}, or they could have had this feature turned off by 
default, with the possibility to turn it on either per jsp page (using some 
page directive like <%@ page staticElReferences="true" %>) or webapp-globally 
in the web.xml. Or, they could simply include the requirement that the class 
name must start with a capital letter, thus only causing problems for people 
who break the coding standard (ie either having a class name starting with a 
lower case letter, or having a variable name starting with an upper case 
letter).

/Jimi

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: Intermittent ClassNotFoundException in Jasper EL evaluation

2016-03-09 Thread Mark Thomas
On 09/03/2016 18:20, jimi.hulleg...@svensktnaringsliv.se wrote:

> Has anyone seen this problem before? What could be the cause of it?

It is a known 'feature' of the new EL requirements added in 3.0. The EL
parser can't differentiate between an attribute without a scope and a
reference to an static field.

See https://bz.apache.org/bugzilla/show_bug.cgi?id=57583

The way to avoid it is to always add an explicit scope (page, request,
application, session) to your attributes.

Suggestions for improvements to the default ImportHandler implementation
to make this faster are welcome.

Mark


-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org