Posts mit dem Label Scala werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Scala werden angezeigt. Alle Posts anzeigen

Donnerstag, 8. November 2012

Marrying Scala with Apache MyFaces Part 4 - Apache MyFaces Extension Scripting

Introduction

In Parts 1 2 and 3 we have had a look at various implementation aspects on how to enable Scala and Apache MyFaces.
Part 4 introduces a framework which allows a zero restart configuration for Scala based JSF artifacts, such as components, managed beans, renderers etc...

This project is a relatively new extension to the Apache MyFaces project which already has had spawned several sideprojects such as CODI or Ext-Val.

The projects name is Ext-Scripting.

What is Ext-Scripting? This is an ongoing effort to integrate scripting languages into Apache MyFaces in a way that the user gets zero restart configurations for code writing.

Following video will give more details on what Ext-Scripting can provide:



Ext-Scripting itself is not only a Scala specific project but also supports as of now Groovy, dynamically recompiled Java  and soon JRuby.
One of the major aspects of Ext-Scripting was to provide extensive documentation which you can find here.

In this blog we will trim down all the information provided to give you the bare essentials in the shortest possible time.

Ext-Script in action

Ext-Script allows you now to edit direct JSF artifacts like managed beans and recompiles those artifacts on the fly. Very similar to JSP, however in JSP you were limited to stateless pages,  Ext-Scripting literally allows you to edit most JSF artifacts no matter if they are stateless or stateful.

It uses sophisticated dependency detection mechanisms on bytecode level, to reload exactly the artifacts it needs to keep the system in a stable state.

Following video (With a Java Example) will demonstrate of what happens exactly



So what does this mean for Scala. Once Ext-Scripting is enabled you can start to write managed beans, components, navigation handlers, phase listeners etc... directly in Scala and have Ext-Scripting do the heavy lifting for you.

Your server restart times will be reduced up to 90% by simply using the dynamic recompilation feature. You even can use the JSF annotations in a dynamic manner, by simply moving them deleting them etc...

Getting started -

Maven config

The easiest way to get started with Ext-Scripting is simply to take one of the example projects provided by the distribution and to start hacking or use maven. We will emphasis on the maven configuration in this blog. To add Ext-Scripting all you need is a working war configuration and then add following entries to your dependency section:

<dependency>
 <groupId>org.apache.myfaces.extensions.scripting</groupId>
 <artifactId>extscript-myfaces20-bundle</artifactId>
 <version>1.0.4</version>
</dependency>


And for the Scala support:

<dependency>
    <groupId>org.scala-lang</groupId>
    <artifactId>scala-library</artifactId>
    <version>2.9.1</version>
</dependency>
<dependency>
    <groupId>org.scala-lang</groupId>
    <artifactId>scala-compiler</artifactId>
    <version>2.9.1</version>
</dependency>


This should add all the needed dependencies automatically to your project.

web.xml

General Setup To have Apache MyFaces picking up Ext-Scripting we have to add following context parameter to the web.xml:

<context-param>
     <description>
         Enables our scripting engine support plugins
     </description>
     <param-name>org.apache.myfaces.FACES_INIT_PLUGINS</param-name>
     <param-value>
         org.apache.myfaces.extensions.scripting.servlet.StartupServletContextPluginChainLoader
     </param-value>
</context-param>

Setting up your source directories

Now theoretically you can start to code. Ext-Script will pick up sources hosted under WEB-INF/scala in your deployment directory. However under normal circumstances this is undesired because you want to have Ext-Scripting to pick up the sources from your real source directories for editing.

So we now have a number of context parameters in the web.xml which will allow Ext-Scripting to pick up your various sources from the source destinations itself.

For Scala following config parameters is relevant:

<context-param>
     <description>Additional comma separated loader paths to allow direct editing on the sources directory instead of the deployment dir
     </description>
     <param-name>org.apache.myfaces.extensions.scripting.scala.LOADER_PATHS</param-name>
     <param-value>
   <some project path>/src/main/webapp/WEB-INF/scala
     </param-value>
</context-param>


Now this is all to have Ext-Script to pick up your sources from the Scala path and you can start. Happy Coding.

[1] Link to Apache MyFaces Ext-Scripting
[2] Marrying JSF and Scala Part 1
[3] Marrying JSF and Scala Part 2
[4] Marrying JSF and Scala Part 3

Ext-Script and TomEE

Introduction:

I just wanted to inform everyone that Apache MyFaces Extension-Scripting works out of the box with Apache TomEE.

 

 What is Apache MyFaces Ext-Scripting?


For all people who don't know what Ext-Script is (probably most of you). Apache MyFaces Extension Scripting short Ext-Script is an Apache MyFaces extension which provides scripting language support and dynamic recompilation for Apache MyFaces. This means you can code the JSF parts of your project in Groovy, Scala, Java and soon in JRuby and you get jsp like dynamic recompilation of those parts for free.

It does not work with all app servers due to server limitations (mostly in the classloader section)  but so far it has been tested with

  • Tomcat
  • Jetty
  • Websphere Liberty Profile
  • Glassfish and
  • TomEE

More information about Apache MyFaces Ext-Scripting here.

This blogpost is about TomEE and how to get it up and running with this excellent lightweight server.

 

What is TomEE:


TomEE is a project, which provides a full JEE Web Profile to a Tomcat, it does not touch Tomcat but provides the entire JEE web profile stack (and more) within a standard Tomcat war container.  Thats right no EAR anymore just drop a war and you will get JSF CDI etc... out of the box from the container.
More information on Apache TomEE here. No more bundling of JSF CDI etc... all is provided by a lightweight servlet container with great startup times.

 

Combination of both


So how do we combine both containers? The answer is simple, drop
Ext-Scripting:

  • extscript-myfaces20-bundle-1.0.4.jar

and its dependencies :

  • commons-beanutils.jar version 1.8.3 or above
  • commons-codec.jar version 1.3 or above
  • commons-collections.jar version 3.2 or above
  • commons-io.jar version 1.4 or above
  • groovy-all.jar version 1.7.2 or above
  • scala-compiler.jar version 2.10.0-M2 or above
  • scala-library.jar version 2.10.0-M2 or above

(Note if you use Maven then Maven will do the job for you) into your war WEB-INF/LIB and set following configuration entries:

<context-param>
        <description>
            Initializes the plugins for our groovy handlers
        </description>
        <param-name>org.apache.myfaces.FACES_INIT_PLUGINS</param-name>
        <param-value> 
            org.apache.myfaces.extensions.scripting.jsf.startup.StartupServletContextPluginChainLoader
        </param-value>
</context-param>


This is the most important entry and under normal Servlet containers now we would be set and could start coding, however we have to set additional parameters for TomEE:

 <context-param>
        <description>Additional comma separated loader paths to allow direct editing on the sources directory instead
            of the deployment dir
        </description>
        <param-name>org.apache.myfaces.extensions.scripting.groovy.LOADER_PATHS</param-name>
        <param-value>
            /whatever/myfaces20-extscript-helloworld/src/main/webapp/WEB-INF/groovy
        </param-value>
</context-param>

<context-param>
        <description>Additional comma separated loader paths to allow direct editing on the sources directory instead
            of the deployment dir
        </description>
        <param-name>org.apache.myfaces.extensions.scripting.java.LOADER_PATHS</param-name>
        <param-value>
            /whatever/myfaces20-extscript-helloworld/src/main/webapp/WEB-INF/java
        </param-value>
</context-param>
    
<context-param>
        <description>Additional comma separated loader paths to allow direct editing on the sources directory instead
            of the deployment dir
        </description>
        <param-name>org.apache.myfaces.extensions.scripting.scala.LOADER_PATHS</param-name>
        <param-value>
            /whatever/myfaces20-extscript-helloworld/src/main/webapp/WEB-INF/scala
        </param-value>
</context-param>

<context-param>
        <description>Additional comma separated loader paths to allow direct editing on the source
        directories of the deployment dir.
        </description>
        <param-name>org.apache.myfaces.extensions.scripting.ruby.LOADER_PATHS</param-name>
        <param-value>
            /whatever/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/ruby
        </param-value>
</context-param>


Those paths point to your source directories hosting the source files. (Note that the Ruby loader paths are only valid with the latest 1.0.5-SNAPSHOTS, 1.0.4 has no Ruby support)

Once done you can start coding in the code hosted at the respective directories.

 More information about setting up Ext-Script can be found here.

Dienstag, 28. Februar 2012

 Marrying JSF and Scala part 3: Custom Components in Scala

Introduction

While JSF2.0 has simlified the component building a lot thanks to the
composite components, there are still usecases when the classical component
building tasks have to be performed.

We showed in part 1 and part 2 how to build the basic JSF artifacts in Scala we now dive deeper into
JSF by showing how to leverage Scala to build your own jsf custom component.

With this article we combine various techniques of Scala for programming custom components.
The case we are going to investigate is a simple hello world component.

A custom component in Scala

First we have a look at the component itself:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import javax.faces.component.{UINamingContainer, FacesComponent}
import java.util.logging.Logger
import javax.faces.event._


/**
 *
 * @author Werner Punz (latest modification by $Author$)
 * @version $Revision$ $Date$
 */

object HelloWorld {
    /*attributes*/
    val ID = "id"
    val SAY_HELLO = "sayHello"

    /*statics*/
    val logger = Logger.getLogger("HelloWorld")
}


/**
 * helper to avoid a problem with the image button being nested in another component
 * takes a calendar as value
 */
@FacesComponent("at.irian.HelloWorld")
@serializable
@ListenersFor(Array(
    new ListenerFor(systemEventClass = classOf[PostRestoreStateEvent]),
    new ListenerFor(systemEventClass = classOf[PostAddToViewEvent])
))
class HelloWorld extends UINamingContainer with StandardComponent {
    /*lets import the attributes due to not having java structs*/

    import HelloWorld._

    def setSayHello2(hello: String) {
        setAttr[String](SAY_HELLO, hello)
    }

    def getSayHello2(): String = getAttr[String](SAY_HELLO, "") + " added text"

    //we now handle the special events
    override def processEvent(event: ComponentSystemEvent) {
        event match {
            case evt: PostAddToViewEvent => logger.info("PostAddToViewEvent called"+getAttr[String](SAY_HELLO,""))
            case evt: PostRestoreStateEvent => logger.info("PostRestoreStateEvent called")
            case _ => {}
        }

        super.processEvent(event)
    }
}
Code a) Custom component

We have a simple component which exposes one additional attribute sayHello2. The component itself is a composite component with an xml template for rendering an performs some listener tasks.

So far so good, however we use several things here which are of interest:

1
2
3
4
5
6
7
8
object HelloWorld {
    /*attributes*/
    val ID = "id"
    val SAY_HELLO = "sayHello"

    /*statics*/
    val logger = Logger.getLogger("HelloWorld")
}
Code b) Singleton
  • A singleton object for static replacements and struct replacements
1
@ListenersFor(Array(...
Code c) Listeners Array
  • A listeners array for combining multiple listeners 
1
with StandardComponent
Code d) trait 
  • a trait instead of a utils class to combine common functionality of components 
1
2
3
4
5
 event match {
            case evt: PostAddToViewEvent => logger.info("PostAddToViewEvent called"+getAttr[String](SAY_HELLO,""))
            case evt: PostRestoreStateEvent => logger.info("PostRestoreStateEvent called")
            case _ => {}
        }
Code e) Type matches
  • matches for types to avoid instanceof cascades
Lets dissect the code parts one by one:


1) Object HelloWorld

Scala does not have neither static variables nor structs, instead of that it provides singletons as language construct.
Static variables simply can be simulated by a singleton and a simple in class import:

1
2
3
4
5
6
7
8
object HelloWorld {
    /*attributes*/
    val ID = "id"
    val SAY_HELLO = "sayHello"

    /*statics*/
    val logger = Logger.getLogger("HelloWorld")
}
Code b) Singleton 

 and then

1
 import HelloWorld._  
 Code f) import

Allows you to import the instance variables and methods as semi native members.

1
logger.info("PostAddToViewEvent called"+getAttr[String](SAY_HELLO,""))
 Code g) import usage

2) Annotation Arrays

1
2
3
4
@ListenersFor(Array(
    new ListenerFor(systemEventClass = classOf[PostRestoreStateEvent]),
    new ListenerFor(systemEventClass = classOf[PostAddToViewEvent])
))
 Code h) annotation array Scala

is simply what would be in Java
1
2
3
4
@ListenersFor({
   @ListenerFor(systemEventClass = classOf[PostRestoreStateEvent]),
   @ListenerFor(systemEventClass = classOf[PostAddToViewEvent])
})
 Code i) annotation array Java

Since this code transition is not quite obvious even within the Scala documentation, it is worth to be noted in this blog.

3) Traits

The most interesting part is the traits part.
First of all, what is a trait. To sum it up, a trait is an abstract class which can be multiply inherited sort of an interface
with code. Now this opens quite a few possibilities.
Common constraints can be isolated and shared among object instances without having to revert to singletons.
Traits can access "this" and can call methods provided by the class as abstract members.

We reuse traits in this case to isolate common component behavior without having to introduce yet another helper class or an
abstract base class. In fact we finally can share this referencing code among components with different base classes without having to introduce our own inheritance hierarchy.

The trait looks like following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
trait StandardComponent {


    def getViewRoot = FacesContext.getCurrentInstance.getViewRoot

    def getLocale: Locale = FacesContext.getCurrentInstance.getViewRoot.getLocale

    def getAttr[T](key: Serializable, default: T): T = {
        val ret = getAttributes().get(key)
        if (ret != null) ret.asInstanceOf[T] else default
    }

    def setAttr[T](key: String, value: T) {
        //note the scala compiler compiles anyref to java.lang.Object
        //in scala itself anyref is one level above Any which is the base
        //of everything scalawise
        getAttributes.put(key, value.asInstanceOf[AnyRef])
    }

    def getAttributes(): java.util.Map[String, AnyRef]

    def reqAttrMap: java.util.Map[String, String] = {
        FacesContext.getCurrentInstance.getExternalContext.getRequestParameterMap
    }


    def getReqAttr(key: String): String = {
        reqAttrMap.get(key)
    }
}
 Code j) Trait

We use only a subset of this functionality namely getAttr and setAttr.




1
2
3
4
   def getAttr[T](key: Serializable, default: T): T = {
       val ret = getAttributes().get(key)
       if (ret != null) ret.asInstanceOf[T] else default
   }
 Code k) getAttr

Here we can see clearly the this reference to the underlying component getAttributes with
 
def getAttributes(): java.util.Map[String, AnyRef]
 
being defined only as interface, which has to be implemented by the component or one of its parents.

4) Match patterns

Now an interesting language part in Scala is the extended matches. Not only you can match in Scala for values, also matches for types and patterns are allowed.
We use the type matches to avoid instanceof if cascades:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
//we now handle the special events
override def processEvent(event: ComponentSystemEvent) {
    event match {
        case evt: PostAddToViewEvent => logger.info("PostAddToViewEvent called"+getAttr[String](SAY_HELLO,""))
        case evt: PostRestoreStateEvent => logger.info("PostRestoreStateEvent called")
        case _ => {}
    }

    super.processEvent(event)
}
 Code l) match patterns

The cases basically replace if instanceof constructs here


 A renderer in Scala

Now what if we want to write the renderer in Scala.
Scala there can support us as well, it has XML support in the language baked in.
Now lets have a look at the renderer (if not done in an xhtml template like it should be)


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import javax.faces.render.{Renderer, FacesRenderer}
import javax.faces.context.FacesContext
import javax.faces.component.UIComponent

@FacesRenderer(componentFamily = "javax.faces.Output", rendererType = "at.irian.HelloWorld")
class HelloWorldRenderer extends Renderer {
    override def encodeEnd(context: FacesContext, component: UIComponent) {

        val responseWriter = context.getResponseWriter,
        val text = component.asInstanceOf[HelloWorld].getSayHello2(),
        val id = component.getClientId

        responseWriter.write(
                <div class="helloWorld" layout="block" id={id}>
                    {text}
                </div>.toString
        )
    }
}
 Code m) renderer

Now the interesting part of this renderer is following code:
1
2
3
4
5
     responseWriter.write(
                <div class="helloWorld" layout="block" id={id}>
                    {text}
                </div>.toString
            )
 Code m) render part

As we can see, we simply write the html directly constructs like     id={id} and {text} allow for inline templating.

There are constraints to this approach
  • We cannot write out partial xml. The xml written always must be complete, hence we cannot simply write an open tag first, call a subclass and then close the tag
  • We do not use the startElement, endElement. The plus side is readability. 
  • In the end a composite component and its direct xhtml rendering should always be the first choice. Xhtml simply is the target platform in most cases why not use xhtml also for the component renderer part.

References
  1. Marrying JSF and Scala Part1
  2. Marrying JSF and Scala Part2
  3. Custom Components in JSF (German)
  4. Scala Documentation