Code Bug Fix: How to use jsf in “namespaced mode”

Original Source Link

In a website we want to integrate some snippets provided by jsf-applications, think of a dashboard-app or a “portal-light”. While analyzing the requirements we came across a blog-post by Arjan Tjims on jsf 2.3 new features, where he mentioned a new “namespaced mode”:

In namespaced mode, which is specifically intended for Portlets but can be used in other environments as well, the partial response is given an id that’s taken to be the “naming container id”. All predefined postback parameter names (such as “javax.faces.ViewState”, “javax.faces.ClientWindow”, “javax.faces.RenderKitId”, etc) are prefixed with this and the naming separator (default “:”). e.g. javax.faces.ViewState” becomes “myname:javax.faces.ViewState”. Namespaced mode is activated when the UIViewRoot instance implements the NamingContainer interface.

Our application might be a usecase for that “namespaced mode”, so we want to give it a try.

We built a MyUIViewRoot where we implemented NamingContainer and wrapped the original UIViewRoot-instance. We registered a MyViewHandler in faces-config.xml which handles the wrapping of the ViewRoot. For testing we used a simple counter-app with two <h:form>-elements (seems to be important).

We find that “namespace mode” seems to be activated, eg the javax.faces.ViewState indeed is prepended by some namespace and becomes j_id1:javax.faces.ViewState:0. But both actions do not work any more – the postback request does not restore the View any more but creates a new one. So with our simple approach we are missing something (btw, removing only the implements NamingContainer from MyUIViewRoot the counter-app works fine again).

  • Is there some documentation, a howto or a working example out there that we have overlooked?
  • How to activate “namespace mode” correctly? What have we missed to make the postback work again?
  • How can we make MyUIViewRoot to prepend the ViewState with myNamespace?

The application is running in a payara-5 application server.

Our index.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
  xmlns:h="http://xmlns.jcp.org/jsf/html"
  xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head/>
<h:body>
  <h:form id="counterForm">
    <h:panelGrid columns="2">
      <h:outputLabel value="Counter" />
      <h:outputText value="#{counterUiController.counter}" />
    </h:panelGrid>
    <h:commandButton value="inc" action="#{counterUiController.incAction}">
      <f:ajax execute="@form" render="@form" />
    </h:commandButton>
  </h:form>
  <h:form id="resetForm">
    <h:commandButton value="reset" action="#{counterUiController.resetAction}">
      <f:ajax execute="@form" render=":counterForm" />
    </h:commandButton>
  </h:form>
</h:body>
</html>

The CounterUiController:

@Named
@ViewScoped
public class CounterUiController implements Serializable {

    private int counter;

    public int getCounter() {
        return counter;
    }

    public void incAction() {
        counter++;
    }

    public void resetAction() {
        counter=0;
    }
}

Our UIViewRoot-Implementation:

public class MyUIViewRoot extends UIViewRoot implements NamingContainer, FacesWrapper<UIViewRoot> {

    private static final Logger LOG = Logger.getLogger(MyUIViewRoot.class.getName());

    private UIViewRoot wrapped;

    public MyUIViewRoot(UIViewRoot wrapped) {
        this.wrapped = wrapped;
        LOG.log(Level.INFO, "new instance created: {0}", this);
    }

    @Override
    public UIViewRoot getWrapped() {
        return wrapped;
    }

    @Override
    public String createUniqueId() {
        return wrapped==null ? null : wrapped.createUniqueId();
    }

    @Override
    public void setId(String id) {
        if( wrapped!=null ) {
            wrapped.setId(id);
        }
    }
    // all other methodes delegated to `wrapped` directly
}

Our ViewHandler:

public class MyViewHandler extends ViewHandlerWrapper {

    private static final Logger LOG = Logger.getLogger(MyViewHandler.class.getName());

    public MyViewHandler(ViewHandler wrapped) {
        super(wrapped);
    }

    @Override
    public UIViewRoot createView(FacesContext context, String viewId) {
        UIViewRoot retval = super.createView(context, viewId);
        retval = wrapIfNeeded(retval);
        LOG.log(Level.INFO, "view created: {0}", retval);
        return retval;
    }

    @Override
    public UIViewRoot restoreView(FacesContext context, String viewId) {
        UIViewRoot retval =  super.restoreView(context, viewId);
        retval = wrapIfNeeded(retval);
        LOG.log(Level.INFO, "view restored: {0}", retval);
        return retval;
    }

    private UIViewRoot wrapIfNeeded(UIViewRoot root) {
        if (root != null && !(root instanceof MyUIViewRoot)) {
            LOG.log(Level.INFO, "view wrapped: {0}, {1}", new Object[] { root, root.getId() });
            return new MyUIViewRoot(root);
        } else {
            return root;
        }
    }
}

You need to replace the UIViewRoot not to wrap it.

public class NamespacedView extends UIViewRoot implements NamingContainer {
    //
}

And then in faces-config.xml.

<component>
    <component-type>javax.faces.ViewRoot</component-type>
    <component-class>com.example.NamespacedView</component-class>
</component>

That’s basically all. See also the Mojarra IT on this.

Tagged : / /

Code Bug Fix: CDI Bean method not called when using myfaces bundled in webapp and run on Wildfly

Original Source Link

I want to migrate my JSF Application from ManagedBean to CDI Beans.

First of all I have done a simple test to see if CDI are working, but they don’t.
Here my example, using Wildfly 10 and myfaces 2.2

beans.xml in .WEB-INF

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
        http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       bean-discovery-mode="all">
</beans>

xhtml page:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">

<h:head>
    <title>
        test
    </title>
</h:head>

<h:body>
    <h:outputText value="#{CDITest.hello}"/>
    <h:outputText value="test"/>
</h:body>

</html>

The backing Bean

import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import java.io.Serializable;

  @Named("CDITest")
  @SessionScoped
  public class CDITest implements Serializable{

    public String getHello(){
      return "Hello";
    }
}

The output

test

No error message (!) and no call to CDITest.getHello() method. What I’m missing?

The problem is more general.
In JSF 2.3, JSF picks up CDI via BeanManager#getELResolver. In pre JSF 2.3, the container or the CDI impl has to marry JSF and CDI.

I think you need to Declare a @FacesConfig annotated class to activate CDI in JSF 2.3

import javax.enterprise.context.ApplicationScoped;
import javax.faces.annotation.FacesConfig;

@FacesConfig
@ApplicationScoped
public class ConfigurationBean {

}

Upgrading to myfaces-2.3.6 (jsf 2.3) on Wildfly 19.0.0 solved the issue. Note that you need a @FacesConfig class as suggested by @Cristyan.

Note also that using Mojarra the issue didn’t happen and the Bean worked as expected (for both Widlfly 10 and Widlfly 19).

Tagged : / / /

Code Bug Fix: Switch PrimeFace socket channel/url dynamically

Original Source Link

Help me on how to switch channel of primeface socket?

Socket Defined As :

<p:socket id="socket" widgetVar="socket" onMessage="processData" autoConnect="true" 
                                            channel="/getData/#{dataBean.registeredId}" />

Depending on the few values selected/changed, registeredId does changes. I need re enable the socket with new registeredId without refreshing the page.

If refreshed new registeredId is considered and data flows in.

What I tried.
Did socket update whenever registeredId is changed.
Tried in javascript like below:

function reInitiateWebsocket(){
    var registeredId= document.getElementById('dataform:registeredId').value;
    var url =  "/getData/"+registeredId;
    PF('socket').disconnect();
    PF('socket').connect(url);
}

javascript call is made from bean

RequestContext.getCurrentInstance().update("dataform:registeredId");
RequestContext.getCurrentInstance().execute("reInitiateWebsocket()");

Still on verifying channel is not changed with new registredId.

Help?

Vishwa

Tagged : / /