Skip to main content

Welcome to Geoff Hayward's Weblog

Commenting on Java, JavaFX, Java EE, Joomla, and IoT.

It turns out that getting EJB timer beans configured into a WildFly 9 domain cluster is quite easy. This post records how I got EJB timers working on a WildFly 9 cluster with a MySQL database as the timer bean's datasource. The domain profile I used was the 'ha' profile.

Note this post deals with EJB timer beans and assumes you already have a WildFly 9 HA domain configured with a MySQL connection.

All I had to do was configure the "timer-service" element. Here is the configuration that worked for me:

<timer-service thread-pool-name="default" default-data-store="clustered-store">
   <data-stores>
       <database-data-store name="clustered-store" datasource-jndi-name="java:/MySqlDS" database="mysql" partition="timer"/>
   </data-stores>
</timer-service>

I have read another posts about configuring a 'timer-service' with PostgreSQL that talked about updating the SQL in the 'timer-sql.properties' file. I found that MySQL just worked without the need to change the 'timer-sql.properties' file.

I created an example project to help validate the configuration. Here is the code from the example project:

MessageManager.java

@Stateless
public class MessageManager {
    
    @PersistenceContext
    private EntityManager em;
    
    public Message save(Message m){
        return em.merge(m);
    }

}

MessageTimer.java

@Stateless
public class MessageTimer {
    
    @Inject
    private MessageManager mm;
  
    @Schedule(hour = "*", minute = "*", second = "*/10", info ="Runs every 10 seconds", persistent = true)
    public void printDate() { 
        Message m = new Message();
        m.setServer(System.getProperty("server.name"));
        m.setTime(new java.util.Date().toString());
        mm.save(m);
    }
  
}

Message.java

@Entity
@Table(name="message")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Message implements Serializable {
    
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;
    private String time;
    private String server;
    // with getters and setters 

}

With this code the message table should get exactly one entry, from a cluster bigger than a size of one, every ten seconds. The instance that runs should be seemingly random.

Note: you need to set 'server.name' for each server in the HA group via the server's 'System Properties'.



Read

JSF Facelets can store the returned value yielded from a call to an EJB. Doing so will mean the EJB does less work.

Let's say you are implementing a Facelet that will display a message stating something like 'No results' when a collection is empty. If the collection is not empty, the Facelet will call the EJB a second time. First to calculate the size of the collection; second to display the data in the collection etc.

Here is an example:

    [...]

    <ui:fragment rendered="#{pages.all().size() == 0}" >
        <h:outputText value="No pages yet." />
    </ui:fragment>
                
    <ui:fragment rendered="#{pages.all().size() > 0}" >
        <h:dataTable value="#{pages.all()}" var="page">
            [...]
        </h:dataTable>
    </ui:fragment>

    [...]

In the example above the Facelet calls the EJB three times. First to calculate the size of the collection; second to display the elements the data table will occupy; third the data from the collection.

How to Store Values in JSF Facelets

The calling to the EJB can be reduced to just once per page render. Calling the backing bean using the ui:param JSF element will store the returned value in a variable.

<f:metadata>
   <ui:param name="pageSet" value="#{pages.all()}" />
</f:metadata>

Using the ui:param JSF element, here is an improved example:

    [...]

    <f:metadata>
      <ui:param name="pageSet" value="#{pages.all()}" />
    </f:metadata>

    [...]

    <ui:fragment rendered="#{pageSet.size() == 0}" >
        <h:outputText value="No pages yet." />
    </ui:fragment>
                
    <ui:fragment rendered="#{pageSet.size() > 0}" >
        <h:dataTable value="#{pageSet}" var="page">
            [...]
        </h:dataTable>
    </ui:fragment>

    [...]

I hope this helps.



Read

Mailing List

Responsive Media

With the ResponsiveMedia plugin for Joomla it is easy to add 3rd party content from YouTube, Vimeo, and Instagram right in to any Joomla! article.

ResponsiveMedia