Table of Contents
MyFaces Ext-Scripting User Guide
After having set up MyFaces Ext-Scripting, you basically can start editing, and be done with the users guide.
Well theoretically anyway, there are some things every user of Extension-Scripting has to take into consideration.
First of all Ext-Scripting in its current incarnation tries to help the programmers every day life. That means, it tries to reduce the number of needed server restarts to the lowest possible minimum which is achievable within the boundaries of Java and JSF.
You won´t get a zero restart configuration, Extension-Scripting tries not to be perfect in this regard, but what you can achieve is a significant reduction on restarts by applying scripting languages and dynamic compilation.
Secondly, we do not try to support every scripting language under the earth, the basic goal is first to get the basics right and then in subsequent releases to add additional scripting languages support.
As is, every scripting language which can compile against the JVM can be supported, currently there is no support for the scripting language API of Java 6. The reason simply is that the API is too limiting for now in what Ext-Scripting tries to achieve. But future extensions like JSR 292 once available might be used to reduce the number of restarts needed.
For now we cannot recommend to use Ext-Scripting in a production environment for live patches, although it theoretically would be possible, and we spent a lot of blood sweat and tears into making the system stable under multithread conditions. For now, however, we simply only can recommend to use Ext-Scripting for development and development only szenarios if you need to hot patch code (deployment without any changes however should be fine). So if you want to hot patch a running installations, we assume it should work fine, but you are on your own.
Behavior and Usage
Using Ext-Scripting once properly setup is straight forward. Usually it comes down to editing, reloading on the browser editing, reloading the page, .... However if you edit within a running configurations keep an eye on the console/log output. All compile errors and messages go automatically into the log.
The editing and reloading cycle also can be seen in this http://www.youtube.com/watch?v=pz-rf8PY1bU&NR=1
The Compiler Output Component
While editing it should be easy to see the compiler output, preferrably in a way JSP does by providing the necessary feedback straight in the browser. To enable this Ext-Scripting provides a component which catches the compiler output of the various engines and sends the feedback straight to the browser.
To see the component in action please follow this video:
What happens basically is that the component catches depending on its attributes the output of one or all supported languages and displays them on the page -> instant displaying of the compiler output -> less turnaround times.
Advanced Dependency Detection
Ext-Scripting tries to avoid as many server restarts as possible. To enable this it needs to unload recompile and load artifacts and the those which reference our changed ones. To enable this, Ext-Scripting does dependency detection on bytecode level as well as on artifact level. This functionality is enabled automatically you wont have anything further to do. You can see it working by watching the output log, if you change a class, you automatically will see that the system marks the classes which reference your changed class as tainted as well.
You have to have in mind that data currently in ram cannot be recovered by the unloading and reloading happening, so everything stored for instance in application or session scope is lost that way.
Following video shows the mechanism working:
This dependency detection works over all dynamic classes, no matter being it classes, interfaces, annotations, and it works over static and dynamic imports.
Javabean dependencies also are detected on artifact level so that if the JSF IOC mechanism is used those bound over neutral Object classes also will reload the dependencies correctly.
Ext-Scripting automatically compiles with the debug flags on. Debugging against a running configuration should be no problem. If the debugger can be pointed towards the sources, debugging should work without any sideffects, due to the fact that the debugger can pick up the debug info from the newly compiled class files. (Note - the classfiles are not altered in any way so in any case you just deal with normal Java classes)
Ext-Scripting supports following JSF 1.2 artifact reloading:
ApplicationFactory reloading on method call level
FacesContextFactory reloading on method call level
LifecycleFactory reloading on method call level
RenderkitFactory reloading on method call level
- Component reloading on component tree creation level
ManagedBeans reloading for all managed beans even session and application scoped ones on request level
All those artefacts are supported on Java and Groovy Level
Ext-Scripting allows following JSF2 artefacts for reloading:
- All major JSF 2 annotations can be used in a dynamic way, annotations can be moved removed or added on the fly
on sources in a running installation
Following diagram shows the structure and what is supported in the various modules of Ext-Scripting.
Page and Resource Reloading
One of the goals of Ext-Scripting is to prevent unnecessary restarts and redeploys during development. To enable this it provides custom functionality outside of the scope of providing scripting capabilities. One of those features is the page and resource reloading from your source directories.
What is this Exactly
Well the diagram above shows the mechanism in a abstract way, to make it short, pages and web-resource are loaded from your resource directory without having to redeploy the web application, changes on them can be watched on the fly simple by a browser reload. There is no need to adjust your web application server or your IDE for auto deployment mechanisms. Unnecessary web application restarts for changed resources can be avoided that way.
Depending on the JSF version used only parts of all of the reloading can be used. For JSF 1.2 installations, only the page reloading can be used, unless you use a third party resource framework which can provide source resource loading.
Weblets for instance provides exactly such a resource loading facility in one of its demo applications, which can be reused.
For JSF 2.0 both web page source loading and resource source loading can be used by simply enabling the correct resource handlers in the web.xml as described in the setup guide.
The basic usage is the same as for sources: Editing -> Refresh -> Check the changes etc...
Follwing video shows JSF2 resource loading as part of our online video component editing example:
- Changes in the web.xml or faces-config are not covered by this mechanism, you have to use the provided auto deploy mechanism
of your IDE and the restart capabilities of your web application and MyFaces to cover those instances for now.
- If a resource is present in the deployment directory but not present anymore in the source directory then it will be picked up from the deployment directory. Otherwise a resource in the source directory always overrules the deployed resource.
Everyone who uses hot plugging systems in Java has to live with the limitations the Java VM imposes to a certain extent. The VM imposes a statically typed programming model and allows hot code replace under certain limitations which do not compromise the structural integrity of a running system.
We cannot lift those restrictions, other ones do not as well, but they try to bypass the limitations under the hood by adding simulation code to dynamic typing or adding proxies underneath the system which allow for more freedom in hot code plugging.
As said before we cannot lift those restrictions either and maybe Java 7 with the JSR 292 will ease them, but fortunately JSF already has certain extension points which allow to some degree to intercept and reload parts of an application if used wisely.
So what internally happens is basically that Ext-Scripting interferes at two points in a running application, first it interferes on artefact level by introducing reloading proxies by using the JSF extension points. Those artifacts can replace the implementations provided by the user at certain safe points of the application lifecycle and on classloader level.
In between several daemon threads and interception points take care of the compile, dependency detection etc... but that should not be of a huge concern to the programmer using the system. The most important aspect for the programmer is that the system under normal circumstances works more or less invisible in the background, only recognizable if you watch its output in the logs or console.
The compilation happens against java classes, so that the system always will work on the java classes generated by the scripting language currently used.
That way the average programmer always will work on unaltered pure class files, which can be debugged, but also will get his code refreshed at usually the next refresh he does in the system. Which means no interference with artificial constructs on class level which could bring a debugger out of context, but still maximum possible reloadability even on classcast an import level as long as it concerns JSF artefacts like Renderers, Components, Converters and Managed Beans!
For the average programmer using Ext-Scripting all of this does not have to be of concern, yet as explained before, under normal circumstances, ext-scripting is almost invisble, but it explains some sidebehavior implementors might encounter while programming deeper in JSF.
First of all, the JSF extension points now have reloading proxies instead of their default implementation. So any cast against a default implementation of an extension point which does not cast against the generic base classes or interfaces is bound to fail
Seconly although Ext-Scripting tries to avoid it, there are certain situations where a classcast exceptions on a class of the same name might occur (it should not but there are system configurations where it still can happen) In this case if the error cannot resolve itself a server restart unfortunately is mandatory. Those corner situations are the 5 - 10% corner cases, where the system cannot be perfect and does not try to be.
In certain situations bean or generally artifact reloading can happen of artifacts which have not been touched, this is caused by the dependency scanner, which tries to keep the system in a reliable state dependencywise. So for instance if you just touch a request scoped bean, some application scoped or session scoped beans which import the bean or cast them on codelevel might be refreshed as well due to their intra code dependencies. The same for instance happens with a renderer which might cast a component if the components code is touched!
Depending on the artifact the reloading behavior might be slightly different. Components for instance need a freshly build component tree otherwise an error in the restore state phase might occur (does not have to be but can), only a freshly built component tree can ensure the integrity of the data and code in this area. Bean refreshes however can happen without any of those sideffects, but again beans might get refreshed which never had been touched to ensure the integrity of the entire system!
JSF can use beans provided by many frameworks, via the EL-Resolver extension point. The main issue in this regard is that JSF once the bean is not provided by JSF is not responsible anymore for the lifecycle but the underlying providing framework is. So reloading and scripting can only work if the framework supports such mechanisms. At the current state only the JSF beans are fully supported for reloading and scripting, although a similar effort within the bounds of this project is under way to support Java reloading for Spring, and Spring also supports some scripting languages in conjunction with its IoC capabilities. So if you need the same capabilities for your framework of choice then check out the documentation or contact the vendor/author of the corresponding framework.