Are you using the “Trinidad” JSF component set, provided by Apache MyFaces ?
If yes, please add your company to this wiki page.
Thanks!
Are you using the “Trinidad” JSF component set, provided by Apache MyFaces ?
If yes, please add your company to this wiki page.
Thanks!
There is a JSR 301, that is about providing a unique standard for a JSF-Portlet Bridge. The spec isn’t ready, but now available for its second Early Draft Review. Oracle donated an implementation to the Apache MyFaces project.
There isn’t a homepage yet, but you can get the source and file issues against the project.
Have fun with this new MyFaces subproject !
Looking at a bug, I noticed some craziness is going on with the unified EL and coercion rules for String. It converts every null object to an empty String.
Take this TLD snippet from the core.tld, for the standard convertDateTime tag:
<attribute>
<name>pattern</name>
<required>false</required>
<deferred-value>
<type>java.lang.String</type>
</deferred-value>
</attribute>
So, the pattern is String, fine. Now imagine this:
<h:inputText value="#{bean.aRegularDate}">
<f:convertDateTime pattern="#{boundToSomeNullValue}" />
</h:inputText>
This does not display the date value. Why ?Simple. The pattern is converted to an empty String (“”) and, when pushing an empty String as the pattern to the SimpleDateFormat class, the format method returns “” as well:
SimpleDateFormat sdf = new SimpleDateFormat("");
System.out.println(sdf.format(new Date()));
For reasons like that, in Trinidad we just do this:
<attribute> ... <name>pattern</name> <deferred-value /> ... </attribute>
So, a tag like this works <tr:convertDateTime pattern=”#{boundToSomeNullValue}” />.See also this bug, which I noticed, during looking at another bug
Almost every 3rd party JSF component library comes with a file-upload-component. So do the Apache MyFaces component libraries Tobago, Tomahawk or Trinidad. This blog speaks about Trinidad, but it is true for other JSF component libraries as well.
Imagine you have a form, to update some data, like the first name or a birth date value. You would have a save-button, that doesn’t cause navigation to stay on the page. And on every submit the the same data goes back to the server, unless you change it, before pressing the save-button:
<tr:form>
<tr:inputText label="Text" value="#{bean.data}" />
<tr:commandButton text="save data" />
</tr:form>
Now imagine you have to add a new field, one to take the picture of the person you are editing. Some HR-Systems have that requirement. A screenshot could look like this:

When you click save, to upload the file, the page rerenders like this:

Now, when you try to click again the save… you’ll notice a validation error, that you have to submit a file. Hey, didn’t I a second before ??

Why is that happening ? Why is the HTML input widget rendering empty, and the regular text-input not ?
One issue is that you can’t render out something like <input type="file" value="mypic.png" />.
And even if you could. What would it upload, in case you don’t have the mypic.png on your box and, hey… to what directory??
So it makes sense that we see this, at least from a security standpoint.
Perhaps a UI-design like this is a bad thing. So, what can you do ? And how to ensure, the editor is able to change the picture again?
Here is a way, how your form could look:
<tr:inputFile label="Photo" required="true"
value="#{worker.photo}"
rendered="#{worker.photo == null}" />
<tr:inputText label="Photo" readOnly="true"
required="true" value="#{worker.photo.filename}"
rendered="#{worker.photo != null}" />
<tr:commandButton returnListener="#{worker.handleReturn}"
partialSubmit="true" immediate="true"
text="Update" rendered="#{worker.photo != null}"
action="dialog:update" useWindow="true"
windowWidth="374" windowHeight="266" />
As you notice, when there is no photo, an inputFile component will be used (see the rendered attribute). In case there is a photo present, for the worker, we will see a readonly inputText and an update-button:

When you now press save, no validation error happens. That helps.The update-button is a bit special. It causes the Trinidad-Dialog-Framework to open a new page (in this case in a new browser-window). The new window shows an inputFile component and a button, to change the picture. Note, here is input field is empty as well, but it doesn’t hurt in this case! So, select a new file…

Once the user is clicking the “save” button in this window, the window closes and via PPR the forum will be updated, to reflect the change:

And again… the SAVE button does cause no validation error. So this could be a solution to the problem. To get this working a little bit Java is needed.
The action method behind the “Save the new photo” button looks like:
public String updater()
{
RequestContext.getCurrentInstance().returnFromDialog(null, null);
return null;
}
And the returnListener from the update-button looks like this, to trigger PPR, to have the new filename visible, once the little window is gone:
public void handleReturn(ReturnEvent event)
{
UIXForm form = (UIXForm) event.getComponent().findComponent("theIdOfMyForm");
RequestContext.getCurrentInstance().addPartialTarget(form);
}
That’s all. Perhaps that helps a bit. A nice overhaul of this exercise would be to create a declarative component, using Facelets!
Thomas Spiegl added a new Orchestra-Demo to the FacesGoodies project. That shows how-to use Hibernate(JPA) + Orchestra. The user-interfaces is using Tomahawk as the JSF-comp. lib.
Have fun!
I updated the SVN version of FacesGoodies. The major change was, that I removed the Apache Shale framework and I added the new Apache MyFaces Orchestra framework. Now I am strongly following the pattern of defining the “JSF beans” only inside of the Spring 2.0 configuration file.
Why? Spring offers a lot of cool support to your application and since Spring 2 introduced (web) scopes, like session or request, you can easily declare these beans inside of the Spring configuration file. The good old faces-config is (in FacesGoodies) only used to specify the Trinidad RenderKit, the Spring VariableResolver and the Navigation rules of the demo application.
I also added some demonstration of the Ajax-APIs of Apache Trinidad (client-side and server-side).
Ah, yes… FacesGoodies is back on JSF 1.1, using MyFaces 1.1.5 and Trinidad 1.0.3 !
Have fun and enjoy the Orchestra test drive!
Sure, the “ViewController” pattern isn’t new. Basically it is the concept of using a specific bean, behind a webpage. In ASP.NET this is called code-behind, AFAIK. Apache Shale has it, and Apache MyFaces Orchestra too.
It might be confusing, that two Apache projects provide the same facility, but that happens
Basically your bean (that lives inside the (Spring) configuration) is named similar like the JSF viewId.
A viewId “editor.xhtml” will map to a bean, named “editor”. A viewId like “staff/editor.xhtml” will map to a bean, that is named “staffEditor”. Not hard to understand.
I personally like the Orchestra ViewController more, compared to the Shale ones. Sure Shale was one of the first implementations out there, that were providing this mechanism for JavaServer Faces. Perhaps JSF 2.0 has something like that ? Let’s wait and see…
Orchestra’s ViewController provides three callbacks:
Not enough, there are currently three options to use them:
The interface way is easy, just implement the interface and its three methods and you are done. The reflection approach is quite interesting. You can have a simple POJO like:
public class CreateController
{
public void initView()
{
...
}
...
}
and your code is called by the framework. No interface or annotation needed. Pretty neat, isn’t it?
Using annotations also has its charm. You can annotated the class with different viewIds and some methods, like:
@ViewController(viewIds={"/all.xhtml"})
public class AllController
{
...
@PreRenderView public void loadUsers()
{
...
}
That enables you to have serveral view to reuse the same ViewController.
More soon!
Categories: Uncategorized
Yes, I was using Apache Shale in my little FacesGoodies demo, but now I move Orchestra in; and Shale out. Why ? Especially Orchestra has more features to deal with ORM frameworks, via Spring.
My FacesGoodies already uses JPA with OpenJPA and HSQLDB, so, not much to add, well more XML isn’t what I like, but it’s ok for now…
What to do? I added a orchestra.spring.xml file, containing these lines of code:
<!-- 1. initialization of all orchestra modules (required for core15 module) --> <import resource="classpath*:/META-INF/spring-orchestra-init.xml" /> <!-- 2. the conversation scopes --> <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"> <property name="scopes"> <map> <entry key="conversation.manual"> <bean class="org.apache.myfaces.orchestra.conversation.spring.SpringConversationScope"> <property name="timeout" value="30" /> <property name="advices"> <list> <ref bean="persistentContextConversationInterceptor"/> </list> </property> </bean> </entry> <entry key="conversation.flash"> <bean class="org.apache.myfaces.orchestra.conversation.spring.SpringConversationScope"> <property name="timeout" value="30" /> <property name="advices"> <list> <ref bean="persistentContextConversationInterceptor"/> </list> </property> <property name="lifetime" value="flash"/> </bean> </entry> </map> </property> </bean> <!-- 3. the "entity manager" manager --> <bean id="persistentContextConversationInterceptor" class="org.apache.myfaces.orchestra.conversation.spring.PersistenceContextConversationInterceptor"> <property name="persistenceContextFactory" ref="persistentContextFactory" /> </bean> <!-- 4. conversation - persistence adapter --> <bean id="persistentContextFactory" class="org.apache.myfaces.orchestra.conversation.spring.JpaPersistenceContextFactory"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean>
Not enough XML so far.
In my web.xml file I needed to add these entries as well:
<filter> <filter-name>orchestraFilter</filter-name> <filter-class>org.apache.myfaces.orchestra.conversation.jsf.filter.OrchestraServletFilter</filter-class> </filter> <filter-mapping> <filter-name>orchestraFilter</filter-name> <servlet-name>faces</servlet-name> </filter-mapping> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <listener> <listener-class>org.apache.myfaces.orchestra.conversation.servlet.ConversationManagerSessionListener</listener-class> </listener>
That is all you need to do.
It took me some time, to correct my xml-based typos…
but than all was fine.
More about the real migration, soon!