4 Replies Latest reply on Apr 19, 2011 1:10 PM by Facundo Miquel

    Portlet get's refreshed across multiple sessions

    Facundo Miquel Newbie

      Hello!

       

      I have a couple of JSF Seam portlets using the Portlet Bridge all extending a BasePortlet that basically has all the runnable interface methods ...

       

      import org.jboss.seam.annotations.In;

      import org.jboss.seam.annotations.Out;

      import org.richfaces.component.html.HtmlExtendedDataTable;

      import org.richfaces.model.selection.SimpleSelection;

       

       

      public abstract class BasePortlet implements Runnable , Serializable {

       

       

          private static Logger logger = Logger.getLogger(BasePortlet.class.getName());

       

       

          @In(required = false)

          @Out(required = false)

          private HtmlExtendedDataTable table;

           ......

       

      public void addListener(EventListener listener) {

              logger.log(Level.INFO,"Adding listener...{0}", portletName);

              synchronized (listener) {

                  if (this.listener != listener) {

                      this.listener = (PushEventListener) listener;

                  }

              }

          }

       

       

          public void run() {

              logger.log(Level.INFO,"Run Start...{0}", portletName);

       

       

              if (startDate == null) {

                  if (thread == null)

                      start();

                  else {

            .....

       

      Portlets

       

      ....

      @Name("policiesBean")

      @Scope(ScopeType.SESSION)

      @PortletScope(PortletScope.ScopeType.APPLICATION_SCOPE)

      public class PoliciesPO extends BasePortlet  {

      .....

       

      ....

      @Name("opportunitiesBean")

      @Scope(ScopeType.SESSION)

      @PortletScope(PortletScope.ScopeType.APPLICATION_SCOPE)

      public class OpportunitiesPO extends BasePortlet {

      .....

       

      now..

       

      I have a third portlet (a search portlet) that basically has a table and when I select a row on that table the other portlets are refreshed using richfaces Ajax to refresh the portlets so the search portlet looks like this...

       

      ....

       

      <rich:extendedDataTable id="resultsTab"

                                      value="#{customers}" var="customer"

                                      height="102px" selectedClass="selected-row"

                                      selection="#{search.selection}" binding="#{search.table}"

                                      selectionMode="single"

                                      onRowMouseOver="this.style.backgroundColor='#F1F1F1'"

                                      onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'"

                                      cellpadding="0" cellspacing="0" >

                  <a4j:support

                      event="onRowMouseUp"

                      action="#{search.rowSelected}" />

                  <rich:column label="Cliente" sortable="true" sortBy="#{customer.name}" width="225px">

                      <f:facet name="header">

                          <h:outputText value="Cliente" />

                      </f:facet>

                      <h:outputText value="#{customer.name}" />

                  </rich:column>

       

      ....

       

      and my portlets...

       

      .....

      <a4j:push interval="1000" eventProducer="#{opportunitiesBean.addListener}"                  reRender="oppPushEvent, opportunitiesTab" enabled="true" id="oppPushEvent" />                    

      ....

       

      Now the SearchPO bean has a method that handles row selection....

       

      ....

       

          public void rowSelected() {

       

       

              logger.log(Level.INFO, "SelectedRow cifID: {0}", selectedRow.getCifId());

              callPortlets(selectedRow);

       

       

          }

       

       

      private void callPortlets(Customer selectedRow) {

              Object responseObject = FacesContext.getCurrentInstance().getExternalContext().getRequest();

       

       

              if (responseObject instanceof ResourceRequest) {

       

       

                  OpportunitiesPO opportunitiesPO = (OpportunitiesPO) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("opportunitiesBean");

                  if (opportunitiesPO != null) {

                      logger.log(Level.INFO, "Encontre el portlet de Oportunidades, lo vacio....." + opportunitiesPO.isEnabled());

                      if (!opportunitiesPO.isEnabled()) {

                          opportunitiesPO.start();

                      }

                      try {

                          opportunitiesPO.executeQuery(selectedRow);

                      } catch (Exception _ex) {

                          logger.log(Level.INFO, "Error llamando al portlet de oportunidades {0}", _ex.getMessage());

                      }

                  }

      ....

       

       

      Now

       

      This all works fine and I search for my customer, select the row and all the portlets on the page get refreshed, the only small detail is that if I have two browsers / machines accesing the portal page, when one person selects a row in the search table all the portles across the browsers and machines get refreshed.. what am I missing?

       

      One last thing.. I downloaded eisode6.zip from vimeo (http://vimeo.com/11484018) that basically show how to use a4j to re-render portlets, I added a table and slowed donw the actions so it will refresh and the same ting happens!!!

       

      I'm uploading the project so you can see.. just compile it, throw it in a GateIn 3.1.0-GA.. add the portlets A B and C to the portal.. open 2 browsers and point both to the newlly created portal page.. in one page use portlet B to write a message and enjoy the show!!!..

       

      You will notice that in both browsers the table for portletC get's refrehed.. (actually the whole portlet get's refreshed, but you will see it more clearly on the table)

       

      TIA

       

      web.xml

       

      <?xml version="1.0" encoding="UTF-8"?>

      <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"

                  xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

          <display-name>salesPortal</display-name>

          <context-param>

              <param-name>org.jboss.portletbridge.ExceptionHandler</param-name>

              <param-value>org.jboss.portletbridge.SeamExceptionHandlerImpl</param-value>

          </context-param>

          <context-param>

              <param-name>javax.portlet.faces.renderPolicy</param-name>

              <param-value>ALWAYS_DELEGATE</param-value>

          </context-param>

          <context-param>

              <param-name>org.ajax4jsf.RESOURCE_URI_PREFIX</param-name>

              <param-value>rfRes</param-value>

          </context-param>

          <context-param>

              <param-name>org.richfaces.LoadStyleStrategy</param-name>

              <param-value>ALL</param-value>

          </context-param>

          <context-param>

              <param-name>org.richfaces.LoadScriptStrategy</param-name>

              <param-value>ALL</param-value>

          </context-param>

          <context-param>

              <param-name>org.ajax4jsf.COMPRESS_SCRIPT</param-name>

              <param-value>false</param-value>

          </context-param>

          <context-param>

              <param-name>A4J.AJAX.Push.URL</param-name>

              <param-value>/salesPortal-web-1.0/faces/a4j.push</param-value>

          </context-param>

          <listener>

              <listener-class>

               org.jboss.seam.servlet.SeamListener

            </listener-class>

          </listener>

          <servlet>

              <servlet-name>Seam Resource Servlet</servlet-name>

              <servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>

          </servlet>

          <servlet-mapping>

              <servlet-name>Seam Resource Servlet</servlet-name>

              <url-pattern>/seam/resource/*</url-pattern>

          </servlet-mapping>

          <filter>

              <filter-name>Seam Filter</filter-name>

              <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>

          </filter>

          <filter-mapping>

              <filter-name>Seam Filter</filter-name>

              <servlet-name>Faces Servlet</servlet-name>

              <dispatcher>FORWARD</dispatcher>

              <dispatcher>REQUEST</dispatcher>

              <dispatcher>INCLUDE</dispatcher>

          </filter-mapping>

          <context-param>

              <param-name>javax.faces.DEFAULT_SUFFIX</param-name>

              <param-value>.xhtml</param-value>

          </context-param>

          <context-param>

              <param-name>facelets.DEVELOPMENT</param-name>

              <param-value>false</param-value>

          </context-param>

          <servlet>

              <servlet-name>Faces Servlet</servlet-name>

              <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>

              <load-on-startup>1</load-on-startup>

          </servlet>

          <servlet-mapping>

              <servlet-name>Faces Servlet</servlet-name>

              <url-pattern>/faces/*</url-pattern>

          </servlet-mapping>

          <servlet-mapping>

              <servlet-name>Faces Servlet</servlet-name>

              <url-pattern>*.seam</url-pattern>

          </servlet-mapping>

          <session-config>

              <session-timeout>10</session-timeout>

          </session-config>

      </web-app>

       

       

      portlet.xml

       

      <portlet-app

                   xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"

                   version="2.0"

                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                   xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd

                                          http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd">

        <portlet>

          <portlet-name>Buscar Clientes</portlet-name>

          <header-content>

              <link rel="stylesheet" type="text/css"

                      href="/stylesheet/master.css" media="screen"/>

          </header-content>

          <portlet-class>

            javax.portlet.faces.GenericFacesPortlet

          </portlet-class>

       

       

          <init-param>

            <name>javax.portlet.faces.defaultViewId.view</name>

            <value>/SearchPO.xhtml</value>

          </init-param>

          <init-param>

            <name>javax.portlet.faces.preserveActionParams</name>

            <value>true</value>

          </init-param>

          <expiration-cache>-0</expiration-cache>

          <portlet-info>

             <title>Buscar</title>

          </portlet-info>

          <supports>

            <mime-type>text/html</mime-type>

            <portlet-mode>VIEW</portlet-mode>

          </supports>

        </portlet>

        <portlet>

          <portlet-name>Oportunidades</portlet-name>

          <header-content>

              <link rel="stylesheet" type="text/css"

                      href="/stylesheet/master.css" media="screen"/>

          </header-content>

          <portlet-class>

            javax.portlet.faces.GenericFacesPortlet

          </portlet-class>

          <init-param>

            <name>javax.portlet.faces.defaultViewId.view</name>

            <value>/ebs/OpportunitiesPO.xhtml</value>

          </init-param>

          <init-param>

            <name>javax.portlet.faces.preserveActionParams</name>

            <value>true</value>

          </init-param>

          <expiration-cache>-0</expiration-cache>

          <portlet-info>

             <title>Oportunidades</title>

          </portlet-info>

          <supports>

            <mime-type>text/html</mime-type>

            <portlet-mode>VIEW</portlet-mode>

          </supports>

        </portlet>

      .....

      </portlet-app>

        • 1. Portlet get's refreshed across multiple sessions
          Facundo Miquel Newbie

          Reading a bi more I dicovered that this might be the intended functionality, to refresh all instances of one specific portlet, to be able to create a, for example, a chat aplication or a bulletin board or something of the sort...

           

          is this correct?

          • 2. Portlet get's refreshed across multiple sessions
            Wesley Hales Master

            I tried to run the demo and got:

            LockTimeoutException: could not acquire lock on @Synchronized component: portletC

             

            As for sessions maintaining state across users/browsers, I'm pretty sure you get a different HTTP session with each portlet APPLICATION_SCOPE related session so there is something going on here. What did you read about this being intended functionality.

            • 3. Re: Portlet get's refreshed across multiple sessions
              Facundo Miquel Newbie

              Yes.. sorry about the @Synchronized thing I had my reRenderds set too low so it got locked, I'm uploading a new exmple with this fixed..

               

              Regarding the session scope you are absoloutly right you do have two instances of the portlet (one per browser)  I've printed out the session Map

               

              for (String key: FacesContext.getCurrentInstance().getExternalContext().getSessionMap().keySet()) {

                            logger.log(Level.INFO, "{0} - {1}", new Object[]{key, FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(key)});

                        }

              portletC portletc = (portletC)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("portletCBean");

              portletc.start();

              portletc.setText(message);

               

              and you get two different instances:

               

              Browser A: 12:41:31,572 INFO  [portletB] portletCBean - org.example.project.portletC@4cae231a

              browser B: 12:42:47,754 INFO  [portletB] portletCBean - org.example.project.portletC@4356544f

               

              but still my table get's refreshed in both browsers at the same time..

               

              Finally, I can't find where I "deduced" that this was the expected functionality.. I'm glad I was wrong now I just need to figure out why this is happening..any clues as to where to look?

               

              TIA!

              • 4. Re: Portlet get's refreshed across multiple sessions
                Facundo Miquel Newbie

                I updated the thread instead of replying to you.. sorry...