How can you force recompilation of jsps in JBoss 4.2? - java

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.
Addendum: Note that we experienced in production recently that even with the accepted answer's flag set the JSPs did not recompile, even though the JSP did in fact change. Major bug there, but regardless, JBoss was shutdown normally. At this point it is getting to be an old version of JBoss, but if you are still using it, deleting the content of the work and tmp directories is the only way to be sure.
I'm not changing the accepted answer simply because it really gets to the point of what the question was looking for. JBoss bugs are kind of a separate issue.

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.

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.

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.

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.

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

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
The compiled version of the jsp needs to be deleted.
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.

Related

tapestry strange behaviour

Well, at least it seems as tapestry issue.
I'm getting an exception when trying to access a specific page:
org.apache.tapestry.PageNotFoundException:
Page 'ASpecificPage' not found in application namespace.
Seems like some pages are found, and some are not, I'm new to this project, and so far cannot say is there any difference between them.
The error still occurs, even when whole jboss-4 instance, along with the deployed application, is copied from my coworkers' computers and run, whereas they do not experience such problems. Supposedly there is no other application-specific configuration, and it's all contained within the server instance.
Any ideas? Even not Tapestry-related? I tried using same java version, with update number precision, but in vain. Like, where should I start to debug?
EDIT:
I'm new to tapestry, so if anything is missing or just inaccurate, just let me know. Some details:
the application is deployed as war, copied to deploy directory,
unexploded
there are other jars copied as well, not sure if they are relevant
when searching for ASpecificPage, it seems that there is only a java
class (i.e. ASpecificPage.java), and there is missing appropriate
.html file
when searched in code, I found occurences like:
clearPopUp(cycle);
ASpecificPage page=(ASpecificPage) cycle.getPage("ASpecificPage");
page.show(cycle, ASpecificPage.TAB_2);
Any other details needed?

Web application deployment under embedded Tomcat 7.0.32

We have been using tomcat 7.0.19 successfully in embedded mode. However recently due to some fixes in our area of concern we decided to move to tomcat 7.0.32. Most things work as expected with same code and newer version, however the war deployment for some reason has'nt worked well. I have a couple of servlets registered with my tomcat. Facing below 2 issues,
Has something changed from 7.0.19 to 7.0.32 from embedded tomcat behavior. To detail this out let me explain the behavior difference, with 7.0.19, i could deploy my application and when i hit the "host:port/contextpath" it loaded the applications start page (i.e. welcome page, this page is UI centric and does not need a server intervention, so none of my servlets get called). However with 7.0.32 the same url results in my servlet being called.
So to debug the problem, i commented most of my code so that i have a vanilla tomcat implementation, just the very basic stuff, i.e. setting the engine name, default host, setting host properties, adding a connector (nio, with default properties) and deploying a war. No servlets and other things, just to check if the very basic stuff works. To my surprise when i ran this code it still failed with the same problem within my servlet, how did that happen, now that my code is commented it does not register any servlets, still where does it find it from? Does embedded tomcat store some old references, which are not getting cleaned on subsequent runs? I tried changing the port, but that too didn't help.
I am hitting the wall here, not able to understand this wierd behavior, if i figure out #2, only then can i make some progress on #1.
Thanks in advance,
Vikram
Figured out what the problems were.
In reverse order,
2 - This actually was a weird behavior with the vanilla embedded tomcat code too invoking the servlets which never were registered in the first place. The problem here was with eclipse, for some reason it picked up the old reference of my class. The moment i ran the same code from outside of eclipse i.e. via command prompt, things were back to normal.
1 - This problem was related to web deployment, in my code i was additionally setting my classloader into WebappLoader and eventually adding my application jars into it. This for whatever reasons worked fine with 7.0.19, however did not with 7.0.32, the moment i externalized all my jars to be loaded during application startup via classpath this problem too was resolved.
Thanks,
Vicky

why tomcat does not require restart when jsp is changed

I have been using JSP,Servlet for quite sometime. I know that whenever we change anything in Servlet we need to restart Tomcat Server to get the changes. Where as in case of JSP change, tomcat does not require restart.
As per my knowledge JSP page gets converted into Servlet only when compiled. So, after all its a Servlet.So, How does it works without Tomcat restart.
I have knowledge of cases when a JSP page gets compiled like on first time access after server restart etc.
Because when Tomcat is asked to execute a JSP, is compares the modification date of the JSP file with the modification time of the compiled class corresponding to this JSP, and if more recent, it recompiles on the fly before executing it.
This is BTW an option that should be turned off in production, because it takes time to perform this check.
See http://tomcat.apache.org/tomcat-7.0-doc/jasper-howto.html for details.
Because by default tomcat is started in development mode, which means JSP-derived servlets recompiled when a change is detected. It's a good questions how does the JVM load the new class - probably the tomcat classloader is configured to do so.
A few related notes:
you can turn off the development option for production
you can have servlets been reloaded as well - you have to start tomcat with a JVM in debug mode.
Not just JSP's some containers also support reloading of servlet class if it is modified.
It is upto the container to decide when to load servlets. A servlet can be loaded at runtime on demand. And coming to JSP, JSP translated to servlet can also be loaded at runtime.
Coming to your question,
Why Tomcat does not require restart?
It is because Tomcat is capable of adding/modifying classpath to Web Application classloader at runtime. Tomcat will be having their custom Classloader implementation which allows them to add the classpaths at runtime.
How does the custom classloader might work?
One way to get this working is when a Servlet/JSP is modified, a new classloader is created for the Servlet/JSP with Application classloader as parent classloader . And the new classloader will load the modified class again.

Using the WebLogic JSP Compiler in Tomcat

We are developing a webapp using WebLogic 10.3.4. our UI team is experiencing pain with the slow turnaround times between a JSP edit and seeing the results in their browser. Things are a lot easier with Tomcat 7.0 but this uses a different JSP compiler from the one we are targetting.
My question is, is it possible to swap out the default compiler in Tomcat and replace with the one from WebLogic? If so, how would I do this? We know that the WebLogic compiler can be called from the command line (we have it in our build). It looked like you could do this with the IBM Jikes compiler in the past, but I can't find any mention of WebLogic.
--- Edited as question changed slightly ---
You cannot easily swap out the Tomcat JSP compiler for another JSP compiler, as the Tomcat JSP compiler is integrated into Tomcat. While all JSP compilers function in a similar manner, the cost of reworking the integration of one system with another compiler is the reason such a swap is not easily performed. Most web containers do not call these compilers out-of-process, but rather they launch them on dedicated threads in the web container.
That said, perhaps you can avoid compilation in the web container alltogether. If you pre-compile your JSP pages with either the Tomcat or the Weblogic JSP compiler, then you can simply package the previous JSP pages into the WAR as .class files, and when the time comes for the first-access of the previously mentioned JSP file, the web container will not have to pause an additional amount above class access time to compile the JSP into a .class file.
JSP compilers are very much like regular Java compilers, with the main exception being that they take JSP files as "source code" instead of .java files. Once you work out the arguments, CLASSPATH, and parameters for your JSP compiler, you can integrate it into your build chain just like you do your regular .java files.
Details on precompiling with Tomcat's JSP compiler.
Some information on precompiling with Weblogic's JSP compiler.
--- Original Post follows ---
Yes, it is possible; provided that the compilers for both support the same release of java, and are configured to compile to the same release of Java.

java web application best practices

I'm trying to figure out the optimum way to develop and release a fairly simple web application, and I'm running into several problems. I'll outline the decisions I've made, because somewhere I've clearly gone off the rails.. Hugely grateful for any help!
I have what I think is a fairly simple web application. It contains a couple of jsps that reference a couple of java beans, and the usual static html, js, css and images.
Decision 1) I wanted to have a clear and clean release procedure, such that I could develop on my local machine and then release reliably to a production machine. I therefore made the decision to package the application into a war file (including all the static resources), to minimize the separate bits and pieces I would need to release. So far so good?
Decision 2) I wanted things on my local machine to be as similar as possible to the production environment. So in my html, for example, I may have a reference to a static file such as http://static.foo.com/file . To keep this code working seamlessly on dev and prod, I decided to put static.foo.com in my /etc/hosts when developing locally, so that all the urls work correctly without changing anything.
Decision 3) I decided to use eclipse and maven to give me a best practice environment for administering and building my project.
So I have a nice tight set up now, except that:
Every time I want to change anything in development, like one line in an html file, I have to rebuild the entire project and then wait for tomcat to load the war before I can see if it's what I wanted. So my questions are:
1) Is there a way to connect up eclipse and tomcat so that I don't have to rebuild the war each time? ie tomcat is looking straight at my actual workspace to serve up the static files?
2)I think I'm maybe making things harder by using /etc/hosts to reflect production urls - is there a better way that doesn't involve manually changing over urls (relative urls are fine of course, but where you have many subdomains, say one for static files and one for dynamic, you have to write out the full path, surely?)
3) Is this really best practice?? How do people set things up so that they balance the requirement for an automated, all-encompassing build process on the one hand, and the speed and flexibility to be able to develop javascript and html and css quickly, as quickly as if one just pointed apache at the directory and developed live? What do people find works?
Many thanks!
Edit: Thanks all for your great responses! If I could mark them all right, I would.. This has really helped me out. What I'm hearing is that best practice is to conserve the structure of the webapp in development, and run it in as close an environment to production as possible. Seems like the differences between people are the extent to which people are prepared to hot deploy resources into the servlet container, circumventing the build process for a little extra speed or convenience. That makes sense. Thanks again.
This is much like what I have to do at work, although we use ant (for now?). Also, while I use an IDE (or two), I refuse to have one as part of my build process, EVER. Somebody needs to be able to understand and tune your build.
Is there a way to connect up eclipse
and tomcat so that I don't have to
rebuild the war each time?
1) I think you're relying too much on your IDE. Usually I have an Ant build.xml that has a couple of tasks: one is "build war" the other is "update jsps." Building the war compiles all the code, packages it, deploys it to Tomcat and restarts everything. Updating the jsps doesn't restart the server, it's just a straight copy from my local files to Tomcat's deployed instance. No restart necessary since they're JSPs. Takes about half a second.
where you have many subdomains, say
one for static files and one for
dynamic, you have to write out the
full path, surely?
2) No way, Jose. So you mean any time the server name changes, you have to recompile your code? If you need to support dynamic URLs you might just want to bite the bullet and take a look at a framework to do the heavy lifting for you. I'm partial to Stripes (which supports dynamic URL rewriting out-of-the-box)... there are others.
To answer #1, I would suggest the following:
Spend some time learning maven to build your .war without eclipse. It's not that hard with the proper archetype. See here for more details: http://maven.apache.org/guides/mini/guide-webapp.html
Maven can generate eclipse projects either through mvn eclipse:eclipse or by using the m2 plugin
For deployment to your local machine and to production, use the maven cargo plugin. http://cargo.codehaus.org/Maven2+plugin and http://blank.jasonwhaley.com/2010/03/automated-deployment-with-cargo-drive.html
To answer question #2, there's nothing wrong with modifying your /etc/hosts file to mimic production. Just have a quick script that lets you add/remove those entries and flushes your dns cache. I do exactly that all of the time. (be sure to make your browser clear its cache frequently also through its relevant setting).
To answer question #3) yes this is how you should be doing things. Each build should result in a single deployable artifact that you can deploy to any of your environments in one step. You need to make sure you can do this without your IDE and use the IDE only as a tool to help you during the development phase.
Others have already answered you, I'll just comment on this (this too long for a comment btw so I make it an answer):
Every time I want to change anything
in development, like one line in an
html file, I have to rebuild the
entire project and then wait for
tomcat to load the war before I can
see if it's what I wanted.
If you change one line in an html file, there's no need to rebuild the entire project.
Note that I always rebuild the full .war and redeploy my .war but this takes less than two seconds (less than one second to rezip the .war [that's really what a .war is, a zipped file] and less than one second to redeploy it) because:
you don't need to recompile your entire project when you simply change one line in an html file
Same when you change one .java file: you can simply recompile that one file and re-war.
I wrote my own Ant build file from scratch (no Maven here) and I've got several targets. I can force a "clean build", that shall re-compile everything but typically I'm simply repackaging and redeploying the .war
You can check it for yourself: build a .war, unzip it in, say, directory dir1, then modify one .html (or one .java/.class file) and build a new .war and unzip that new .war in, say, dir2.
Then compare dir1 and dir2: now fix your build process so that you can create that second .war without needing to recompile everything.
Changing one .html, .java, .jsp, .css, .js / whatever file and redeploying a new .war should be a matter of seconds (less than two seconds if you didn't throw the kitchen sink in your Webapp).
Note that on the very same project, another developer here prefers to "hot deploy" / replace the files directly in the exploded webapp (I prefer to redeploy a .war everytime and because my complete repackage/redeploy takes less than two seconds I'm fine with it that way).
You don't need to reconstruct war file if your project is an Dynamic Web App in Eclipse and configured Tomcat server properly. Follow the below instructions:
1) Check out the below of how to configure tomcat server with eclipse:
http://greatwebguy.com/programming/eclipse/make-eclipse-and-tomcat-play-nice-together/
2) Use relative paths for your application but not absolute paths.
3) If you follow the above 2 steps properly then you have a best environment for development.
during development, you should configure eclipse and tomcat so that no rebuild/redeloy is required. just modify html/css/jsp etc, save, and refresh browser to see the result.
but before deploying to production site, you should do a clean full build and test it carefully.
domains: they should be in a config file; dev and prod should have different config files.

Categories

Resources