Monday, September 23, 2013

Liferay: Create a quartz job scheduler

In two ways a job can be scheduled in Liferay.
  1. Configure  in liferay-portlet.xml
  2. Implement it in code.
1. Configure  in liferay-portlet.xml
  1. Override the property 'scheduler.enabled = true' in portal-ext.properties.
  2. Create a new dummy portlet in liferay-portlet.xml as follows,
     <portlet>  
         <portlet-name>job</portlet-name>  
         <scheduler-entry>  
             <scheduler-event-listener-class>com.madrone.portal.job.PortalJob</scheduler-event-listener-class>  
             <trigger>  
                 <simple>  
                     <simple-trigger-value>5</simple-trigger-value>  
                     <time-unit>minute</time-unit>  
                 </simple>  
                 <!-- cron>  
                     <property-key>0 0 0 * * ?</property-key>  
                 </cron-->  
             </trigger>  
         </scheduler-entry>  
     </portlet>  
    
  3. Add this portlet in portlet.xml
     <portlet>  
          <portlet-name> job</portlet-name>  
          <display-name>Job</display-name>  
          <portlet-class>  
              com.madrone.portal.job.PortalJob  
          </portlet-class>  
          <supports>  
               <mime-type>text/html</mime-type>  
               <portlet-mode>view</portlet-mode>  
          </supports>  
          <security-role-ref>  
               <role-name>administrator</role-name>  
          </security-role-ref>  
          <security-role-ref>  
               <role-name>guest</role-name>  
          </security-role-ref>  
          <security-role-ref>  
               <role-name>power-user</role-name>  
          </security-role-ref>  
          <security-role-ref>  
               <role-name>user</role-name>  
          </security-role-ref>  
     </portlet>  
    
  4. Create a job listener
     public class PortalJob implements MessageListener {  
         private static final Log LOG = LogFactory.getLog(PortalJob.class);  
        
         @Override  
       public void receive(Message arg0) {  
         LOG.info("PortalJob: Starts" );  
         // your code   
         LOG.info("PortalJob: Stops" );         
       }  
     }  
    
2. Implement it in code. 
  1. Override the property 'scheduler.enabled = true' in portal-ext.properties.
  2. Create an action class which is run during server startup
     public class PortalStartupAction extends SimpleAction {  
       private static final Log LOG = LogFactory.getLog(PortalStartupAction .class );  
       
       @Override  
       public void run(String[] arg0) throws ActionException {  
         LOG.info("Preparing to Schedule the job: PortalJob" );  
         Thread thread = Thread. currentThread();  
         try {  
                 SchedulerEngineUtil. schedule(PortalJob.SCHEDULER_ENTRY, thread.getContextClassLoader());  
         } catch (SchedulerException e) {  
           throw new ActionException(e);  
         }     
         LOG.info("PortalJob scheduled successfully." );  
       }  
     }  
    
  3. Configure the above action class in portal-ext.properties
     #  
     # Application startup event that runs once for every web site instance of  
     # the portal that initializes.  
     #  
     application.startup.events=com.madrone.portal.util.PortalStartupAction  
    
  4. Create a job
     public class PortalJob implements MessageListener {  
         private static final Log LOG = LogFactory.getLog(PortalJob.class);  
       
         @SuppressWarnings("serial" )  
         public static final SchedulerEntry SCHEDULER_ENTRY = new SchedulerEntryImpl() {  
              {  
              setDescription( "Job that get triggered every 5 minutes");  
                
              setTriggerType(TriggerType. SIMPLE);  
              setTimeUnit(TimeUnit. MINUTE);  
              setTriggerValue( "5");  
                
              //setTriggerType(TriggerType.CRON);  
              //setTriggerValue("0 0 0 * * ?"); // Fire at 12:00 AM every midnight  
              // Reference: http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger  
              setEventListenerClass(PortalJob.class.getName());  
              }  
         };  
       
         @Override  
         public void receive(Message arg0) {  
             LOG.info("CRPortalERPJob: Starts" );  
                 // your code  
           LOG.info("CRPortalERPJob: Stops" );         
       }  
     }  
    

Wednesday, September 4, 2013

Observer pattern

Java has two utility classes to serve Observer pattern - Observer and Observable. 
  • The aim of this pattern is to notify the objects of Observer class, when a change is done to the objects of Observable class.
  • Observer class should implement Observer interface and override the method 'update'.
  • Observable class should extend Observable class. The key method of this class is 'setChanged()'. This marks the Observable object being changed, only then the notifyObservers() will notify the observer objects that a change was done to the observable object. The notifyObservors() makes call to the Observor's update() method.
  • How do the observable object knows its observers? The observers should be added to the observable objects using the methods addObserver() of Observable class. An observer can be added or removed from the observable object.
 
1:  import java.util.ArrayList;  
2:  import java.util.List;  
3:  import java.util.Observable;  
4:  import java.util.Observer;  
5:    
6:  public class ObserverPattern {  
7:        
8:      public static void main(String []args) {          
9:          Stock s = Stock.getInstance();  
10:          s.setName("Madrone");  
11:          s.setNumShares(10);  
12:            
13:          // Observers  
14:          List<Buyer> buyerList = new ArrayList<Buyer>();  
15:          buyerList.add(new Buyer("A"));  
16:          buyerList.add(new Buyer("B"));  
17:            
18:          for(Buyer b : buyerList) {  
19:              s.addObserver(b);  
20:          }  
21:            
22:          for(int i=0; i<10; i++) {  
23:              s.setNumShares(s.getNumShares() + 1); // Observed object is modified   
24:              s.notifyObservers();  
25:          }      
26:            
27:          System.out.println("Shares available: " + s.getNumShares());  
28:          for(Buyer b : buyerList) {  
29:              System.out.println(b.getName() + " : " + b.getNumShares());  
30:          }  
31:      }  
32:  }  
33:    
34:  class Buyer implements Observer {  
35:        
36:      private String name;  
37:      private int numShares;  
38:        
39:      Buyer(String name) {  
40:          this.name = name;  
41:      }  
42:    
43:      @Override  
44:      public void update(Observable observable, Object ob) {          
45:          Stock s = (Stock) observable;  
46:          if(s.getNumShares() > 0) {  
47:              buyAShare();  
48:              s.setNumShares(s.getNumShares() - 1);  
49:          }      
50:      }  
51:        
52:      private void buyAShare() {  
53:          this.setNumShares(this.getNumShares() + 1);  
54:      }  
55:        
56:      public String getName() {  
57:          return name;  
58:      }  
59:      public void setName(String name) {  
60:          this.name = name;  
61:      }  
62:      public int getNumShares() {  
63:          return numShares;  
64:      }  
65:      public void setNumShares(int numShares) {  
66:          this.numShares = numShares;  
67:      }  
68:  }  
69:    
70:  // Singleton class  
71:  class Stock extends Observable {  
72:        
73:      private String name;  
74:      private int numShares;  
75:        
76:      public static final Stock INSTANCE = new Stock();  
77:      private Stock() {}  
78:            
79:      public static Stock getInstance() {  
80:          return INSTANCE;      
81:      }  
82:        
83:      public String getName() {  
84:          return name;  
85:      }  
86:      public void setName(String name) {  
87:          this.name = name;  
88:      }  
89:      public int getNumShares() {  
90:          return numShares;  
91:      }  
92:      public void setNumShares(int numShares) {  
93:          this.numShares = numShares;  
94:          setChanged();  
95:      }  
96:  }