Help

Controls

PermLinkWikiLink

Built with Seam

You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.

Forum: Seam Users Forum ListTopic List
22. Feb 2008, 00:17 CET | Link

I have built a groovy builder that can build part of the jsf component tree in a request and take advantage of existing components in facelets including user tag libraries. You could do something like this:


u.component (rendered: "#{el}") {
  h.form {
    (0..10).each { idx ->
      h.inputText (value: "#{bean.map[idx]}")
    }
  }
}

It uses a servlet context based script engine pointing to a tmp dir in order to have a compile on change method for speed.

I really think it would be a good addition to the seam framework and wanted to see if I could get any feed back.

25 Replies:
22. Feb 2008, 09:52 CET | Link

Looks very, very interesting... This could help in constructing some large and complex layouts, where Facelets are sometimes quite cumbersome... Conditional building of large components tree could be very efficient here. Mikchail Grushinskiy might be happy with this :).

Is this only an experiment? I think if you could implement a non-toy example application (or better a real, working deployment) to proof stability, resource-wise processing and performance gains (if any) your idea would gain well-deserved attention.

Good work! Keep informing us, please!

23. Feb 2008, 00:07 CET | Link

I have a working deployable toy-like app that does nothing but show some possibilities. I am using this already to run a few pages on a professional site, I cannot mention its name here. Any ideas on a non-toy example application? I can make it, but ideas on what people would want to see escape me.

25. Feb 2008, 17:23 CET | Link

A couple of other things I have in this is 1) a seam map, and 2) an entity query language wrapper.

If you need a seam component you can do this:


  def mycomp = seam.mycomponentName

If you want to outject


  seam.mycomponentName = []

You can even outject a datamodel:


  def array = []
  (1..100).each { array.add("Item $it") }
  seam.setDataModel("myDataModel", array)

Now similiar to the Sql() for normal groovy, if you have your entity manager bound to jndi in the persistence.xml, you can reference it and do something like this:


  def q = new Eql("java:/EMBoundName")
  
  h.html {
    body {
      h.dataTable("#{myDataModel}", var: "row") {
        h.column("#{row}")
      }

      table {
        caption("EQL Results")
        q.eachRow("SELECT e FROM Entity e") { entity ->

          tr{
            td(entity.field1)
            td(entity.field2)
            td(entity.field3)
          }

        }
      }
    }
  }
29. Feb 2008, 23:52 CET | Link

In addition to what I have above in respone to Gavin, I have a new feature called a g component. What it allows you to do is provide a closure that gets ran at RENDER time instead of TREE creation time, and practically becomes a custom component. It comes with a MarkupBuilder wrapped around the ResponseWriter for the faces context. So you could do something like this (x is the automatically provided markup builder for the closure, and the call is passed the current faces context and the custom component, the closure for the tag builder will also add children to the custom component which can be rendered as a string with comp.renderChildren()):


  u.component {

    g({ ctx, comp ->
      x.table {
        (0..10).each { row ->
        x.tr {
          x.td("Column 1")
          x.td(comp.renderChildren())
        }
        }
      }
    }) {
      h.outputText("This will be rendered over and over at
                    render time by the g component")
    }

  }
07. Mar 2008, 03:42 CET | Link

So can you get the following to work:

ui.composition {

  template: "template.xhtml";

  @In(create=true) Person person;

  ui.define {

    name: "body";

    h1 { "Change password" }
 
    h.form {

      "Enter new password:"

      h.inputText {
        value: Value {
          get: { return person.password; }
          set: { person.password = it; }
        }
      }

      h.commandButton {
        value: "Set password!", 
        action: { person.setPassword(); }
      }

    }
  }
}

If you can get the code above working, I think you should definitely productize this work, and I would be very happy to host it as a subproject of seamframework.org.

 

Learn more about Web Beans...

08. Mar 2008, 00:29 CET | Link

Well, this looks a tad bit more difficult. I think I will definitely need the help of a groovy master. There is no indication at all that groovy will allow me to access any type of fields in normal scripts and/or closures.

The best I can do so far is this:


viewOnly = false
person = seam.person
ui.composition ( template: "template.xhtml" ) {

  ui.define (name: "body") {

    h1("Change password")
 
    h.form {

      print "Enter new password:"

      h.inputText("#{persona.name}")

      h.commandButton("Set password!", action: { 
         person.setPassword(); }
      })

    }

  }
}
08. Mar 2008, 03:17 CET | Link

So, just to clarify, the problem is that you can't make the field injection work? 'cos this is not a class definition?

OK, I'll take a closer look at how this stuff works in Groovy and I bet I should be able to come up with some ideas.

 

Learn more about Web Beans...

09. Mar 2008, 03:06 CET | Link

Yeah, field injection is the main thing that I cannot see how to make work. I am loading the groovy files with the GroovyClassLoader which is the most flexible for the scheme I currently have. I originally used the GroovyScriptEngine, but I could not control virtual package names (based on web context and page path) with that so I moved over to the class loader method for embedding. By any means it still compiles it as a Script class, and that script class does not reveal the field in any manner or form neither for the script itself nor for any closures/sub closures. I was thinking of seeing if there is any kind of runtime proxying or compile time techniques that might allow more insight on the structure of a groovy compiled class.

19. May 2008, 19:05 CET | Link

In reality the following, which is practically the same as your request works just fine in gracelets... the obvious differences is that instead of using annotation based injection, it uses groovy property resolution tied to the seam context. I was wondering if there was some reason why you would want the annotation to be used instead of property resolution. With annotations the users would have to always import the annotation classes and the domain classes into each script which would seam to make the scripts rely more on particular classes and also require more coding on the developers part... but just was curious what you think about the below example in relation to your requested example...


ui.composition(template: "template.xhtml") {

  ui.define(name: "body") {

    h1("Change password")
 
    h.form {

      print "Enter new password:"

      h.inputText (
        value: Value {
          get: { return person.password; }
          set: { person.password = it; }
        }
      )

      h.commandButton("Set password!", 
         action: { person.setPassword(); }
      )

    }
  }
}
05. Jun 2008, 00:41 CET | Link

There is some documentation available now, I will be adding more on a regular basis. The docs are found at:

http://gracelets.sourceforge.net/

23. Feb 2008, 07:21 CET | Link

Very nice, but what I would like to see done differently is Groovy closures instead of Unified EL expressions. This would require you to be able to transparently wrap up a closure as a unified EL MethodExpression or ValueExpression, but that should be totally doable, I suppose.

 

Learn more about Web Beans...

24. Feb 2008, 03:08 CET | Link

Do you mean something like this:


h.form {

  h.commandButton("Click Here", action: { someMethod(); })

  div {
    b({ return "I want this printed"; })
  }

}

def someMethod () {
  // Code would go here for the action when invoked
}

That just might be plausible... not sure how transparent it would be, but I will look into. Maybe I could call it GEL.

24. Feb 2008, 05:14 CET | Link

Not sure about it after initial prototyping and investigation, may need to get some help from someone that is more proficient with making ELResolvers and or coming up with some other solution.

The only thing plausible that I could come up with in a simple ELResolver is the following concept (say we are on a page called index.jsf):


h.form {
  h.commandButton("Click Here", action: "#{index.someMethod}")
}

def someMethod () {
  // action method code
}
27. Feb 2008, 07:10 CET | Link

No, you won't be able to do it with an ELResolver, you'll need to actually create you own impl of MethodExpression that just calls the closure. Don't use EL at all.

 

Learn more about Web Beans...

28. Feb 2008, 04:20 CET | Link

I admit I am not an expert in how everything is linked together in JSF but my first attempts reveal that I have to make a decision. In order to have the benefit of using existing facelet libraries I have to do one of 2 things:

1. Work in conjunction with the DefaultFaceletFactory as I am doing currently.

2. Re-write (basically cut and paste and modify) the whole facelet factory code and compile my own facelets jar (not very practical) but would allow me to truly intercept things correctly.

The drawback to option 1 is that because of how things chain up even though I create my own MethodExpression via a custom wrapper ExpressionFactory the default facelet context gets in the way and does not propogate it down, and with old JSF 1.1 code(which still seems to be used in JSF 1.2) the action source does not seem to care what MethodExpression was used, it simply extracts the expression string and fails horribly. If someone more expirienced has a better idea on how to get the MethodExpression implementation to be used by all parts of JSF then I am open to suggestions.

In any case, I am at my wits end on how to get facelets and thus JSF to use the MethodExpression or ValueExpression implementations I have made. Maybe I am approaching it from the wrong angle, but I probably need to get with someone more familiar with the whole EL technology in order to have a chance at making this work.

01. Mar 2008, 22:53 CET | Link

Lewis,

I think you're definitely on to something here, and it's something that's useful for JSF as a whole. Is the code specifically tied to Seam in any way?

I'm doing a session at JSFDays in a couple of weeks about Scrpiting in JSF, and I'd love to see some of your work. Please drop me a line either here or personally when you get the chance.

---
Kito D. Mann - JSF EG memeber, Author, JavaServer Faces in Action
http://www.virtua.com - JSF/Java EE consulting, training, and mentoring
http://www.JSFCentral.com - JavaServer Faces FAQ, news, and info

04. Mar 2008, 17:05 CET | Link

Kito Mann,

In reality the stuff I am developing is not directly related to Seam, but we are heavy seam users and thought this was a great forum to bring the idea out on the table and get some feedback. We have had the experience that the seam forum is very responsive in comparison to other places that have not seemed to pay much attention to our posts.

Also we would like to see it form part of the seam framework if it is deemed worthy and makes sense to the seam team.

Lewis

06. Mar 2008, 03:13 CET | Link

Lewis,

I see what you're saying about Seam. Regardless of where it ends up, I'd love to be able to show some of this next week at JSFDays. Have you posted it anywhere yet?

---
Kito D. Mann - JSF EG memeber, Author, JavaServer Faces in Action http://www.virtua.com - JSF/Java EE consulting, training, and mentoring
http://www.JSFCentral.com - JavaServer Faces FAQ, news, and info

18. Mar 2008, 22:03 CET | Link

Kito Mann,

I have it on sourceforge (gracelets) now. It is compatible at the moment and barely tested with the following jars:

jsf-facelets.jar (1.1.13) el-ri.jar el-impl.jar jsf-api.jar (Sun JSF RI 1.2) jsf-impl.jar groovy-all-1.5.1.jar log4j.jar

I have converted the seam booking example over to gracelets for a proof of concept example, but I need to study up on the open source licenses to make sure I don't do anything wrong, ill post here when I have that example available to the public.

19. Mar 2008, 23:06 CET | Link

On the source forge site I have a redone seam-booking example ear downloadable. Make sure you get the booking-ds.xml from the original example and put that in your deploy directory along with the ear, it should load up and you should be able to access it from the /seam-booking context.

04. Apr 2008, 19:40 CET | Link

I have a new package and jboss 4.2.0 deployable war for a sort of documentation that is more of a documentation by example at the Source Forge Download Page. As long as you have jsf 1.2 and the el libs which is standard with jboss 4.2.0 available it should deploy fine.

In the beginning of this project it did not directly rely on seam, but after many changes and advances it is not heavily dependant on seam.

04. Apr 2008, 19:44 CET | Link

CORRECTION: It is heavily dependant on seam.

29. Feb 2008, 19:42 CET | Link

Well, I think I have finally figured it out. I am now able to create groovy method and value expression implementations and have them propogated down so that the jsf components use it transparently.

I have also made some more advancements. Instead of using a temp directory I have writting a wrapper ViewHandler for the FaceletViewHandler implementation. It allows the view id's to be regular groovy files, and I have a GraceletCompiler that intercepts groovy view id's. This has the benefit of editing with normaly groovy editors and also being able to debug the gracelet page.

I think this is moving in a better direction than I had originally thought, of course it needs alot of testing for stability and efficiency purposes, but things look very hopeful.

26. Feb 2008, 17:50 CET | Link

Just to make sure we are on the same note... the purpose of what I have made is to work ontop of facelets and really hide it, when you do want to see all that xml. Not to complement facelets directly.

In other words, what you mentioned about closures may have been more towards something like this:


<html:commandButton action="{groovy expression}"/>

When in reality what I am proposing here is this:


<gracelets:page viewOnly="false">
...groovy/gracelet code...
</gracelets:page>

In other words, the whole page would be groovy building the entrie facelet handler tree and allowing arbitrary groovy code to execute along side it. Anyways, thought I should mention more clearly the purpose and objective of what I have created which may not be entirely clear from the original posts.

04. Mar 2008, 18:52 CET | Link

Congratulations! Very good idea! I love it!