views:

2229

answers:

6

I hit on this nasty behavior on JBoss 4.2 in QA, and I want to nip it in the bud before we go into production and find some other corner case.

A jsp calles a method that had the following signature:

 public void methodName(String arg)

This was changed to:

 public void methodName(String arg, Object... args)

A pre-existing JSP called this method via:

 methodName("param");

On deployment of the modified code, JBoss did not recompile the JSP and this caused a crash in QA. Adding a silly comment to the jsp fixed the problem (JBoss recognized that the JSP changed and recompiled it).

Is there a setting on JBoss to force recompilation of JSPs on restart?

EDIT: To clarify some points in the answer, the setup is that the JSPs are part of a war which is part of an ear. The ear has all classes in it, in a jar.

Regarding the desire to pre-compile, if the system doesn't think that the jsp needs compilation, will pre-compile force recompilation? It doesn't seem so. The error here is not a compliation error, it is a method invocation error because of the "changed" (at the byte code level, not really at the code level) method signature.

A: 

I don't know of a setting, but deleting the generated Java class file in the work directory of your JBoss instance will cause the JSP to be recompiled the next time it is called.

Mr. Will
Thanks, but that would be difficult to do practically during the production deployment.
Yishai
A: 

You coudl alter the JBoss startup scripts to explicitly delete the "tmp" and/or "work" directories, where the compiled JSPs are stored. JBoss would then have no choice but to recompile them all.

Not subtle, but it would do the job.

skaffman
A: 

One option for you would be to precompile all of your jsp's at build time. This would quickly flag any compilation errors.

You could also do this in production - speeding up first access but I get the feeling you want this more for a QA step than anything else. If so, you could add the precompile step to the your testing phase in your build tool of choice - and so to your CI environment. This would provide assurance that jsp's that don't compile won't make it out of test.

See this for details on running a precompile task:

Jboss Jasper configuration

Hope this helps.

Pablojim
Thanks, we do this actually. The issue is the build script complies clean, and in a clean compile, the example is fine. The problem here is the underlying JSP needed to be recompiled to work even though it didn't change, and the recompilation would work, but the JSP won't work without recompilation.
Yishai
Fair enough it won't find this error on build. Have you considered precompiling on production?
Pablojim
How do you precompile on production (what setting do you use)? Will it recompile everything?
Yishai
I think I'm be missing something about your setup. Are the JSP pages part of a WAR that contains the modified code? Or is the modified code packaged up seperately?If they are part of the same war then precompiling will help - just run the ant task and the precompiled jsp files will be output as classes - then package up the WAR and deploy.If they are not part of the same WAR then I think your best bet is to delete the work folder. If you don't want to risk this add a simple unix script to the jboss startup that touches some or all of the jsp files to change their modification time.
Pablojim
A: 

Some JSP containers (as per section 8.4.2 of the JSP 1.2 specification) support the capability of precompiling a JSP page.

To precompile a JSP page, access the page with a query string of ?jsp_precompile

http://hostname.com/mywebapp/mypage.jsp?jsp_precompile

The JSP page will not be executed. If the container supports precompilation, the JSP page will be compiled if necessary.

See also http://www.rgagnon.com/javadetails/java-0414.html

RealHowTo
+5  A: 

If the JSPs are part of a WAR that is part of an EAR that is being deployed as a jar, then I'm not clear why your JSPs are not being recompiled. Don't the JSPs in the war file have newer timestamps than their JBoss-compiled class files from the last deploy? If not, couldn't you touch the JSPs as part of building the WAR/EAR before deploying. [I'm referring to using the Unix "touch" command, not manually touching each JSP file.]

Alternatively, the DeleteWorkDirOnContextDestroy setting in $JBOSS/server/default/deploy/jboss.web.deployer/META-INF/jboss-service.xml may be what you are looking for. It is false by default, but setting it to true may be what you need. I think this should delete the JSPs' class files on redeploy so that they get recreated upon first access of each JSP.

See https://jira.jboss.org/jira/browse/JBAS-3358 for more info.

Bert F
Great! I'll check that it works, and if it does accept the answer.
Yishai
+1 Thanks! Just to note in JBoss 5.1.0GA the equivalent file is $JBOSS/server/default/deplyers/jbossweb.deployer/META-INF/war-deployers-jboss-beans.xml
David Waters
Thanks, this solved a problem I had with jsp changes not been reflected after a deploy.
Janek Bogucki
A: 

Pablojim is on the right track. You just need some more info to get a complete view of what's going on. Here's how I understand it.

In prod, you've changed a jsp that requires other jsps to be recompiled. In order for them to be recompiled one of 2 things must happen

  1. The compiled version of the jsp needs to be deleted.
  2. The jsp itself needs to be modified (or even if it's "touched" - modified date is updated)

If you still need to verify that all your jsps work, they will all need to be precompiled using an ant task. this also allows you to deploy the war file with the precompiled jsps in the war file. This should solve your problem.

If your files are not deployed in a war file, but in an exploded format, you should seriously consider packaging your web app in a war file for deployment. This makes it a nice package to deploy between environments.

Mike Pone
It is deployed in a war, and I do verify with precompilation, but the results of the precompilation are just thrown away, so JBoss is making its own decisions about recompilation, and in this case not being agressive enough.
Yishai