Trinidad and Seam

Generally speaking, Trinidad and Seam work together quite well. However there are a couple of minor issues to consider

* Conflicting file upload mechanisms

Both Seam and Trinidad come with code to handle file uploads. Without any extra configuration neither way works, because there are conflicts between the two. I have not found an easy way to use Seam's file upload handling. However you can disable Seam's file upload mechanism and use Trinidad's by adding this to your components.xml:

<components xmlns="http://jboss.com/products/seam/components"
            xmlns:web="http://jboss.com/products/seam/web"
    ...

    <web:multipart-filter disabled="true"/>

* Trinidad dialogs and Seam conversations don't hook up together automatically.

Here is a solution that is tested with both heavyweight and lighweight dialogs on Trinidad 1.2.7 and Seam 2.0.2:

1. Pass the conversation id as a request parameter: Note the <f:param> tag. The param name ("cid") must match the conversation id parameter name defined in components.xml: <core:manager conversation-id-parameter="cid"/>

<tr:commandLink id="capabilitiesPopup"
                action="#{documentHome.readCompanyCapabilities}"
                immediate="true"
                partialSubmit="true"
                text="Edit"
                useWindow="true"
                windowWidth="660"
                windowHeight="630">
    <f:param name="cid" value="#{conversation.id}"/>
</tr:commandLink>

2. Use an extended PageFlowScopeProvider to forward the request parameter to the dialog page (Seam will automatically pick it up and restore the conversation):

package com.eekboom.seamidad;

import org.apache.myfaces.trinidad.context.PageFlowScopeProvider;
import org.apache.myfaces.trinidadinternal.share.url.EncoderUtils;
import org.apache.myfaces.trinidadinternal.context.PageFlowScopeProviderImpl;
import org.jboss.seam.core.Manager;

import javax.faces.context.FacesContext;
import java.util.Map;

/**
 * Extends the Trinidad default PageFlowScopeProvide, so that the Seam conversation id is propagated if passed a a request parameter.
 */
public class SeamPageFlowScopeProviderImpl extends PageFlowScopeProvider {
    private PageFlowScopeProvider pageFlowScopeProvider = PageFlowScopeProviderImpl.sharedInstance();

    public SeamPageFlowScopeProviderImpl() {
    }

    @Override
    public Map<String, Object> getPageFlowScope(FacesContext context) {
        return pageFlowScopeProvider.getPageFlowScope(context);
    }

    @Override
    public Map<String, Object> pushPageFlowScope(FacesContext context, boolean copyParent) {
        return pageFlowScopeProvider.pushPageFlowScope(context, copyParent);
    }

    @Override
    public Map<String, Object> popPageFlowScope(FacesContext context, boolean discardScope) {
        return pageFlowScopeProvider.popPageFlowScope(context, discardScope);
    }

    @Override
    public String encodeCurrentPageFlowScopeURL(FacesContext context, String url) {
        url = pageFlowScopeProvider.encodeCurrentPageFlowScopeURL(context, url);

        Map<String, String> requestParameterMap = context.getExternalContext().getRequestParameterMap();
        String conversationIdParameterName = Manager.instance().getConversationIdParameter();

        String conversationId = requestParameterMap.get(conversationIdParameterName);
        if (conversationId != null && conversationId.length() > 0) {
            url = EncoderUtils.appendURLArguments(url, new String[]{conversationIdParameterName, conversationId});
        }
        return url;
    }
}

3. Configure the custom PageFlowScopeProvider Create a file META-INF/services/org.apache.myfaces.trinidad.context.PageFlowScopeProvider with the content

com.eekboom.seamidad.SeamPageFlowScopeProviderImpl

Here is an alternate solution for JSF 1.1/Seam 1.2: On the Seam JBoss forums, user "dajevtic" provided the following solution (the original is at http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3995439#3995439)


we used Seam and Trinidad in several of our POCs. No production applications yet, though. I remember that we had to incorporate an additional phase listener along with an action listener configured in faces-config when using the dialog framework of Trinidad / ADF, because the conversation id was not propagated to the dialog. Otherwise, there are no known incompatibility issues. We even use AJAX4JSF to "ajaxify" non-ajax components.

Here is the code to get dialogs of trinidad to work w/ seam: PhaseListener: Code:

        private static final String CONVERSATION_ID_SESSION_PARAMETER = "conversationId";

        private Map createParameterMapForConversationRestore(String conversationId) {
                Map paramterMap = new Hashtable();
                paramterMap.put(CONVERSATION_ID_SESSION_PARAMETER, conversationId);
                return paramterMap;
        }

        private void restoreConversation(Context context) {
                if (context.isSet(CONVERSATION_ID_SESSION_PARAMETER)) {
                        String convId = context.get(CONVERSATION_ID_SESSION_PARAMETER).toString();
                        Manager.instance().restoreConversation(createParameterMapForConversationRestore(convId));
                        context.remove(CONVERSATION_ID_SESSION_PARAMETER);
                }
        }

        public void afterPhase(PhaseEvent event) {
                try {
                        if (event.getPhaseId().equals(PhaseId.RESTORE_VIEW)) {
                                UIViewRoot root = event.getFacesContext().getViewRoot();
                                if (root != null) {
                                        String viewId = root.getViewId();
                                        if ((viewId != null) && viewId.endsWith("_dlg.jspx")) {
                                                restoreConversation(Contexts.getSessionContext());
                                        }
                                }
                        } else {
                                log.info("after " + event.getPhaseId());
                        }
                } catch (Exception e) {
                        log.error("Could not restore Seam conversation", e);
                }
        }

Here is the code for the action listener: Code:

        public void processAction(ActionEvent actionEvent)
                        throws AbortProcessingException {

                if (actionEvent.getComponent() instanceof CoreCommandLink) {
                        CoreCommandLink link = (CoreCommandLink)actionEvent.getComponent();
                        if (link.isUseWindow()) {
                                Contexts.getSessionContext().set("conversationId", Manager.instance().getCurrentConversationId());
                        }
                }
                super.processAction(actionEvent);
        }

The example above assumes that popup dialogs end with a _dlg.jspx extensions, which you may alter to your desire.

Please remember, those were quick and dirty hacks in order to get conversations working with Trinidad. This issue may have already been resolved, and if not there might be far better solutions.

Hope it helps.

Kind regards, dj


* Trinidad's resource servlet might not funcion correctly if the following line is not added to Seam's components.xml.

<web:context-filter url-pattern="/adf/*"/>

Issues fixed in current versions

* Seam's validateAll works only with Seam 1.2.1 or later.

* Seam's integration of Hibernate validators does not work, if you are using Trinidad 1.2.x and Facelets.

* Enhanced EL (parameter passing to action listener) does not work

Trinidad_And_Seam (last edited 2010-02-09 17:56:31 by A. Nieves)