Catching Expected And Unexpected Faults In BPEL

In BPELs in WebSphere Integration Developer we can catch exceptions – faults from a BPEL, like during an invoke for example.

image

What happens when we want to catch an exception that is not necessarily a fault and could stem from the underlying  system or the application behind the invoke(in the diagram it is InvokeSomeOperation)?

As you can see in the above excerpt of a BPEL, we have a known Fault called MyApplicationFault in the catch and then in the Catch All we deal with any unknown faults that are not MyApplicationFault and just exceptions that are not BPEL faults at all.

So if we have a NumberFormatException for example it will pass the MyApplicationFault catch and go the Catch All.

Now if we want to transform any exception that comes through in a BPEL exception that will be like a fault we can use an anonymous class in a snippet:

 

new BpelException(){

 

public String getFaultName() {

return “MyFaultName”;

}

 

public String getMessage() {

return caughtException.getMessage();

}

};

 

This way we can handle the exception elsewhere in the BPEL Process using:

com.ibm.bpe.api.BpelException bpelexception =

getCurrentFaultAsException();

logger.debug(“Fault Name” +

bpelexception.getFaultName());

bpelexception.printStackTrace( System.out);

Throwable rootCause = bpelexception.getRootCause();

 

So the Catch All can accept normal java exceptions as well as BPEL faults Smile

Posted in Computers and Internet, IBM, Java programming, JavaScript, Uncategorized, WebSphere, WID 6.0, WID 7 | Tagged , , , , , , | Leave a comment

Securing a BPEL in WebSphere Integration Developer 7 difference over WebSphere Integration 6

 

Hi, another day in the windy city Smile Today we look at how to add a role-based security to secure a BPEL.

In WebSphere Integration Developer(WID) 6 there was no direct way to add a role to a BPEL at assembly level.

In WID 7 we can assign a role to the whole BPEL this could not be done in WID 6. It makes security much easier.

All you have to do is open your assembly diagram as in our example project below:

image

 

 

Click anywhere on the assembly diagram. Then click Properties on the BPEL and then click All Qualifiers.

Expand ExtractionProcess. As you can see above the is Security Identity. Here you can place a security role:

image

 

There you have it the entire Process is secured. On deployment make sure that role is allocated to a user that should have access to the BPEL application:

image

That’s all there is to it! Enjoy Smile

Posted in Computers and Internet, IBM, Java programming, JavaScript, Uncategorized, WebSphere, WID 6.0, WID 7 | Tagged , , , , , | Leave a comment

LTPA Tokens For JAX-RPC and JAX-WS in IBM WebSphere Server Version 7. Client and Provider communication.

 

HAPPY NEW YEAR!!!! To all the followers of this blog. I changed jobs in the later half of last year 2011 and as a result neglected my blog. I hope to turn things around this year Smile

Today we are going to look at JAX-RPC and JAX-WS communication in IBM WebSphere Server 7.  We will look at communication using LTPA tokens and passing LTPA version 1 and LTPA version 2 tokens for authentication.

We will show how to setup the client bindings and provider bindings to enable this communication. This will be of particular importance when legacy applications for WebSphere 6 and earlier need to communicate with Websphere 7 clients.

This will revolve around Provider Policy Set Bindings and Client Policy Set Bindings .

In this article we assume that we have two applications the first is a legacy provider application from IBM WebSphere Server 6 that uses JAX-RPC, (we will call this application LegacyProviderApp1) and we have a new client application from IBM WebSphere Server 7 that uses JAX-WS.

Now LTPA tokens version 1 are compatible with JAX-RPC so here we will show how to setup a client binding that uses LTPA version 1 tokens as seen below:

image

image

Go to Services> Policy Sets> General client policy bindings> New:

image

 

From Add select WS-Security.  Under WS-Security we have various options:

image

We are interest in Authentication and protection. Note you will add the necessary information for Keys and certificates, Message expiration and Custom Properties according to your design specifications.

After clicking Authentication and protection we look at Authentication tokens:

image

Here we have created two Authentication tokens: gen_signltpaproptoken and gen_signltpatoken

gen_signltpatoken is configured as follows:

image

The Namespace URI ending with 5.0.2 is LTPA version 1 which is compatible with JAX-RPC.

Now if you want to ensure that only LTPA version 2 tokens are supported and accepted then select Token type>LTPA Token v2.0

image

The gen_signltpaproptoken is configured as follows:

image

We can actually setup multiple client bindings. So we can have two. One for LTPA version1 tokens and another for LTPA version 2 tokens.

Now we look at the setup of the provider.

Go to General provider policy set bindings>New and create a new binding:

image

Name it to LegacyProviderApp1Provider and then Add> WS-Security. Once again we are interest in Authentication and protection. Note you will add the necessary information for Keys and certificates, Caller, Message expiration and Custom Properties according to your design specifications.

image

Now click on Authentication and protection. Again we are interested only in Authentication tokens :

image

image

Click on con_ltpatoken (this means consumer Smile)

image

If you select LTPA Token v2.0 but you do not check Enforce token version. Then this provider will be able to generate tokens that are LTPA version 1 and LTPA version 2 compatible. This will also aid in JAX-RPC communication for applications designed under WebSphere 6 and below.

The details for con_ltpaproptoken are as follows:

image

 

There you have it we have setup Provider Bindings and Client Bindings that will enable communication using LTPA version 1 and version2  tokens. Smile

Posted in Uncategorized | Tagged , , , , , | Leave a comment

Jasper Reports – Fields And Fonts On Different Operating Systems

Jasper Reports – Fields And Fonts

I have been using Jasper Reports for a while and an interesting senario came to light. This is to do with fields been truncated on linux systems when the report is generated.

For example if we generate a csv file and in the report we have a field as follows:

<textField isBlankWhenNull=”true”>
<reportElement x=”76″ y=”0″ width=”63″ height=”11″/>
<textElement>
<font size=”6″/>
</textElement>
<textFieldExpression class=”java.lang.String“>

<![CDATA["'" + $F{user_id}]]></textFieldExpression>
</textField>

The above generated a report in which the field user_id (which is 18 characters wide) displayed all 18 characters on Windows Vista but on linux it truncated the last two and we only had 16 characters displaying.

On researching the issue I found that this problem had in deed manifested itself in a few places on the internet.

I found out that the different ways each operating systems handles the fonts caused this problem.

Increasing the width solved this partially:

<textField isBlankWhenNull=”true”>
<reportElement x=”76″ y=”0″ width=”70″ height=”11″/>
<textElement>
<font size=”6″/>
</textElement>
<textFieldExpression class=”java.lang.String“>

<![CDATA["'" + $F{user_id}]]></textFieldExpression>
</textField>

However another problem came to light and this was that on different versions of SUSE the generated report appeared differently.

On one version it printed correctly yet on another it still truncated the field.

When running a uname -arv on the machine that worked we have:

admin: uname -arv
Linux xserver1 2.6.5-7.257-nh1 #4 SMP Tue Jun 6 15:45:06 SAST 2006 i686 i686 i386 GNU/Linux

When running uname -arv on the machine that didn’t work we have:

admin: uname -arv
Linux xserver2 2.6.5-7.244-xeon #3 SMP Tue Nov 28 14:18:50 SAST 2006 i686 i686 i386 GNU/Linux

Seems the differences in the build version of the kernel make a difference which is an interesting observation .

The problem was resolved by extending the width once again:

<textField isBlankWhenNull=”true”>
<reportElement x=”76″ y=”0″ width=”87″ height=”11″/>
<textElement>
<font size=”6″/>
</textElement>
<textFieldExpression class=”java.lang.String“>

<![CDATA["'" + $F{user_id}]]></textFieldExpression>
</textField>

 

This time it worked on all three machines.

Posted in Computers and Internet, Java programming, JavaScript, Uncategorized | 1 Comment

Struts 2 and JQuery Example project with Jasper for Reporting

In continuation to my last article I will give the code needed for a Struts 2 and JQuery project. I will call the project TransportBooking. The important additions we make to JQuery is Jasper reporting which will add reporting functionality to the results in our grid.

Please note I will try to outline as much of the source code as I can to aid and assist in getting a sample project up and running. I also focus on the lesser known parts like multiple search criteria for JQGrid. I have seen many questions on this on the web.

The outline of the project is:

The classes are as follows:

The EditTransportBookingAction and JsonTableAction use the JQuery plugin to give a web frontend that is searchable and has the ajax effects for the webpage. Hibernate is used as ORM and we use hibernate projections for the queries.

The EditTransportBookingAction.java looks like:

package za.co.transporter.transportbooking.action;

import java.util.Date;
import java.util.StringTokenizer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.hibernate.Transaction;

import com.googlecode.s2hibernate.struts2.plugin.annotations.TransactionTarget;

import com.opensymphony.xwork2.ActionSupport;

import za.co.transporter.transportbooking.dao.TransportBookingDao;
import za.co.transporter.transportbooking.model.TransportBooking;

@Results( {
      @Result(name = “error”, location = “messages.jsp”)
    })
public class EditTransportBookingAction extends ActionSupport {

      private static final long serialVersionUID = -3454448309088641394L;
      private static final Log  log              = LogFactory.getLog(EditTransportBookingAction.class);

      private TransportBookingDao      TransportBookingDao     = new TransportBookingDao();
     
      private String            oper             = “edit”;
      private String id;
        private String name;
        private String phone;
        private String cellnumber;
        private Date confirmBy;
        private String transport;
     

      @TransactionTarget
      protected Transaction     hTransaction;

      public String execute() throws Exception
      {
        log.debug(“Edit Customer :” + getId());

        TransportBooking customer;

        try
        {
          if (getOper().equalsIgnoreCase(“add”))
          {
            log.debug(“Add Customer”);
            customer = new TransportBooking();

            int nextid = TransportBookingDao.nextTransportBookingNumber();
            log.debug(“Id for ne Customer is ” + nextid);
            customer.setBookingId(nextid);
            customer.setName(getName());
            customer.setPhone(getPhone());
            customer.setCellnumber(getCellnumber());
            customer.setConfirmBy(getConfirmBy());
            customer.setTransport(getTransport());
           
            TransportBookingDao.save(customer);
          }
          else if (getOper().equalsIgnoreCase(“edit”))
          {
            log.debug(“Edit Customer”);

            customer = TransportBookingDao.get(Integer.parseInt(getId()));
            log.debug(customer.getBookingId());
            customer.setName(getName());
            log.debug(customer.getName());
            customer.setPhone(getPhone());
            log.debug(customer.getPhone());
            customer.setCellnumber(getCellnumber());
            log.debug(customer.getCellnumber());
            customer.setConfirmBy(getConfirmBy());
            log.debug(customer.getConfirmBy());
            customer.setTransport(getTransport());
            log.debug(customer.getTransport());
           
            TransportBookingDao.update(customer);
          }
          else if (getOper().equalsIgnoreCase(“del”))
          {
            StringTokenizer ids = new StringTokenizer(getId(), “,”);
            while (ids.hasMoreTokens())
            {
              int removeId = Integer.parseInt(ids.nextToken());
              log.debug(“Delete Customer ” + removeId);
              TransportBookingDao.delete(removeId);
            }
          }

          // Commit changes
          hTransaction.commit();
        }
        catch (Exception e)
        {
          hTransaction.rollback();
          addActionError(“ERROR : ” + e.getLocalizedMessage());
         
          for(int i=0; i < e.getStackTrace().length && i < 4 ;i++)
              addActionError(“ERROR : ” + e.getStackTrace()[i]);
         
          addActionError(“Is Database in read/write modus?”);
          return “error”;
        }
        return NONE;
      }

    public void setId(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getPhone() {
        return phone;
    }

    public void setCellnumber(String cellnumber) {
        this.cellnumber = cellnumber;
    }

    public String getCellnumber() {
        return cellnumber;
    }

    public void setConfirmBy(Date confirmBy) {
        this.confirmBy = confirmBy;
    }

    public Date getConfirmBy() {
        return confirmBy;
    }

    public void setTransport(String transport) {
        this.transport = transport;
    }

    public String getTransport() {
        return transport;
    }

    public void setOper(String oper) {
        this.oper = oper;
    }

    public String getOper() {
        return oper;
    }

     
    }

The IndexAction.java looks like:

package za.co.transporter.transportbooking.action;

public class IndexAction {

}

The JsonTableAction.java looks like:

package za.co.transporter.transportbooking.action;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.interceptor.SessionAware;
import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import za.co.transporter.transportbooking.dao.TransportBookingDao;
import za.co.transporter.transportbooking.model.TransportBooking;

import com.opensymphony.xwork2.ActionSupport;

@Result(type = “json”)
public class JsonTableAction extends ActionSupport implements SessionAware{

  private static final long serialVersionUID = 5078264277068533593L;
  private static final Log  log              = LogFactory.getLog(JsonTableAction.class);

  // Your result List
  private List<TransportBooking>   gridModel;

  // get how many rows we want to have into the grid – rowNum attribute in the
  // grid
  private Integer           rows             = 0;

  // Get the requested page. By default grid sets this to 1.
  private Integer           page             = 0;

  // sorting order – asc or desc
  private String            sord             = “asc”;

  // get index row – i.e. user click to sort.
  private String            sidx;

  // Search Field
  private String            searchField;

  // The Search String
  private String            searchString;

  // he Search Operation
  // ['eq','ne','lt','le','gt','ge','bw','bn','in','ni','ew','en','cn','nc']
  private String            searchOper;

  // Your Total Pages
  private Integer           total            = 0;

  // All Records
  private Integer           records          = 0;
 
  //Multiple Search
  private String filters;

  private Map session;

  private TransportBookingDao      transportBookingDao     = new TransportBookingDao();

  public String execute()
  {
    log.debug(“Page ” + getPage() + ” Rows ” + getRows() + ” Sorting Order ” + getSord() + ” Index Row :” + getSidx());
    log.debug(“filters :” + filters);

    // Calcalate until rows ware selected
    int to = (rows * page);

    // Calculate the first row to read
    int from = to – rows;

    //JSON Object
    JSONObject jsonFilter = null;
   
    //Multiple search filters
    if(filters != null){
        log.debug(“filters :” + filters);   
        jsonFilter = (JSONObject) JSONSerializer.toJSON( filters );
    }
   
   
    // Criteria to Build SQL
    DetachedCriteria criteria = DetachedCriteria.forClass(TransportBooking.class);

   
    if(jsonFilter != null ){
         String groupOp = jsonFilter.getString(“groupOp”);
         log.debug(“groupOp :” + groupOp);
        
         JSONArray rules = jsonFilter.getJSONArray(“rules”);
         int rulesCount = JSONArray.getDimensions(rules)[0];
         log.debug(“Count Rules :” + rulesCount);
        
         for (int i = 0; i < rulesCount; i++) {
               JSONObject rule = rules.getJSONObject(i);
               log.debug(“field :” + rule.getString(“field”));
               log.debug(“op :” + rule.getString(“op”));
               log.debug(“data :” + rule.getString(“data”));
              
              
                   if (rule.getString(“field”).equals(“bookingId”)){

                       Integer searchValue = Integer.parseInt(rule.getString(“data”));
                       if (rule.getString(“op”).trim().equals(“eq”)) criteria.add(Restrictions.eq(rule.getString(“field”), searchValue));
                       else if (rule.getString(“op”).trim().equals(“ne”)) criteria.add(Restrictions.ne(rule.getString(“field”), searchValue));
                       else if (rule.getString(“op”).trim().equals(“lt”)) criteria.add(Restrictions.lt(rule.getString(“field”), searchValue));
                       else if (rule.getString(“op”).trim().equals(“gt”)) criteria.add(Restrictions.gt(rule.getString(“field”), searchValue));
                       else if (rule.getString(“op”).trim().equals(“ge”)) criteria.add(Restrictions.ge(rule.getString(“field”), searchValue));
                       else if (rule.getString(“op”).trim().equals(“le”)) criteria.add(Restrictions.le(rule.getString(“field”), searchValue));

                   }else if (rule.getString(“field”).equals(“name”) || rule.getString(“field”).equals(“phone”) || rule.getString(“field”).equals(“cellnumber”) || rule.getString(“field”).equals(“confirmBy”) || rule.getString(“field”).equals(“transport”)){

                       if (rule.getString(“op”).trim().equals(“eq”)) criteria.add(Restrictions.eq(rule.getString(“field”), rule.getString(“data”)));
                       else if (rule.getString(“op”).trim().equals(“ne”)) criteria.add(Restrictions.ne(rule.getString(“field”), rule.getString(“data”)));
                       else if (rule.getString(“op”).trim().equals(“lt”)) criteria.add(Restrictions.lt(rule.getString(“field”), rule.getString(“data”) + “%”));
                       else if (rule.getString(“op”).trim().equals(“gt”)) criteria.add(Restrictions.gt(rule.getString(“field”), “%” + rule.getString(“data”) + “%”));
                       else if (rule.getString(“op”).trim().equals(“ge”)) criteria.add(Restrictions.ge(rule.getString(“field”), “%” + rule.getString(“data”) + “%”));
                       else if (rule.getString(“op”).trim().equals(“le”)) criteria.add(Restrictions.le(rule.getString(“field”), “%” + rule.getString(“data”) + “%”));

                   }
              
              
           }
    }

    // Count TransportBooking
    records = transportBookingDao.countByCriteria(criteria);

    // Reset count Projection
    criteria.setProjection(null);
    criteria.setResultTransformer(Criteria.ROOT_ENTITY);

 
    // Get TransportBooking by Criteria
    gridModel = transportBookingDao.findByCriteria(criteria, from, rows);

    // Set to = max rows
    if (to > records) to = records;

    // Calculate total Pages
    total = (int) Math.ceil((double) records / (double) rows);

    if( getSession() != null){
        log.debug(“Session exists”);
       
        if(getSession().get(“reportsList”) != null){
            getSession().remove(“reportsList”);
        }
        getSession().put(“reportsList”, gridModel);
    }else{
        log.debug(“Session does not exist. Creating New Session”);
        setSession(new HashMap<String, Object>());
        getSession().put(“reportsList”, gridModel);
    }
   
    return SUCCESS;
  }

  public String getJSON()
  {
    return execute();
  }

  /**
   * @return how many rows we want to have into the grid
   */
  public Integer getRows()
  {
    return rows;
  }

  /**
   * @param rows
   *          how many rows we want to have into the grid
   */
  public void setRows(Integer rows)
  {
    this.rows = rows;
  }

  /**
   * @return current page of the query
   */
  public Integer getPage()
  {
    return page;
  }

  /**
   * @param page
   *          current page of the query
   */
  public void setPage(Integer page)
  {
    this.page = page;
  }

  /**
   * @return total pages for the query
   */
  public Integer getTotal()
  {
    return total;
  }

  /**
   * @param total
   *          total pages for the query
   */
  public void setTotal(Integer total)
  {
    this.total = total;
  }

  /**
   * @return total number of records for the query. e.g. select count(*) from
   *         table
   */
  public Integer getRecords()
  {
    return records;
  }

  /**
   * @param record
   *          total number of records for the query. e.g. select count(*) from
   *          table
   */
  public void setRecords(Integer records)
  {

    this.records = records;

    if (this.records > 0 && this.rows > 0)
    {
      this.total = (int) Math.ceil((double) this.records / (double) this.rows);
    }
    else
    {
      this.total = 0;
    }
  }

  /**
   * @return an collection that contains the actual data
   */
  public List<TransportBooking> getGridModel()
  {
    return gridModel;
  }

  /**
   * @return sorting order
   */
  public String getSord()
  {
    return sord;
  }

  /**
   * @param sord
   *          sorting order
   */
  public void setSord(String sord)
  {
    this.sord = sord;
  }

  /**
   * @return get index row – i.e. user click to sort.
   */
  public String getSidx()
  {
    return sidx;
  }

  /**
   * @param sidx
   *          get index row – i.e. user click to sort.
   */
  public void setSidx(String sidx)
  {
    this.sidx = sidx;
  }

  public void setSearchField(String searchField)
  {
    this.searchField = searchField;
  }

  public void setSearchString(String searchString)
  {
    this.searchString = searchString;
  }

  public void setSearchOper(String searchOper)
  {
    this.searchOper = searchOper;
  }

  public void setFilters(String filters) {
      this.filters = filters;
  }

  public String getFilters() {
      return filters;
  }

  public void setSession(Map session) {
        this.session = session;
    }

    public Map getSession() {
        return session;
    }
 
 
}

In the above class note that we have are using multiple search criteria in our queries meaning that on the front end we can filter by a group of items at once hence why we have filters and jsonFilter. Also we use hibernate projections to build our query.

Now we look at the JasperCsvAction.java. The is where we use jasper reports to generate our reports. This overcomes the problem that the Struts-JQuery plugin lacks reporting tools.

package za.co.transporter.transportbooking.action;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.ResultPath;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.views.jasperreports.*;

import net.sf.jasperreports.engine.JasperCompileManager;

import za.co.transporter.transportbooking.model.TransportBooking;

import com.opensymphony.xwork2.ActionSupport;

@Result(name=”success”, type=”jasper”, params={“location”, “/transportbooking_template.jasper”, “dataSource”, “reportsList”, “format”, “CSV”,”documentName”,”transportbooking.csv” })
public class JasperCsvAction extends ActionSupport implements SessionAware{

    /** List to use as our JasperReports dataSource. */
    private List<TransportBooking> reportsList;
  
    private Map session;
   
    private static final Log  log              = LogFactory.getLog(JasperAction.class);
   
    public String execute() throws Exception {

        log.debug(“Creating Reporting”);      
        log.debug(reportsList);
       
        reportsList = (List<TransportBooking>) getSession().get(“reportsList”);
        // Normally we would provide a pre-compiled .jrxml file
        // or check to make sure we don’t compile on every request.
        try {
            JasperCompileManager.compileReportToFile(
                    “F:/programming-tools/apache-tomcat-7.0.2/webapps/web-deploy/transportbooking_template.jrxml”,
                    “F:/programming-tools/apache-tomcat-7.0.2/webapps/web-deploy/transportbooking_template.jasper”);
        } catch (Exception e) {
            e.printStackTrace();
            for(int i = 0; i < e.getStackTrace().length; i++)
            log.debug(e.getStackTrace()[i]);
            return ERROR;
        }

        return SUCCESS;
    }

    public List<TransportBooking> getReportsList() {
        return reportsList;
    }

    public void setReportsList(List<TransportBooking> reportsList) {
        this.reportsList = reportsList;
    }
   

    public void setSession(Map session) {
          this.session = session;
      }

      public Map getSession() {
          return session;
      }
   
   

}

Also note that the above is for illustrative purposes- In reallife we cannot recompile the jasper report for every user this could lead to a terrible bottle-neck in programs!

The other Jasper actions are similar we just change the output in the @Results as is shown for JasperExcelAction.java

package za.co.transporter.transportbooking.action;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.ResultPath;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.views.jasperreports.*;

import net.sf.jasperreports.engine.JasperCompileManager;

import za.co.transporter.transportbooking.model.TransportBooking;

import com.opensymphony.xwork2.ActionSupport;

@Result(name=”success”, type=”jasper”, params={“location”, “/transportbooking_template.jasper”, “dataSource”, “reportsList”, “format”, “XLS”,”documentName”,”transportbooking.xls” })
public class JasperExcelAction extends ActionSupport implements SessionAware{

    /** List to use as our JasperReports dataSource. */
    private List<TransportBooking> reportsList;
  
    private Map session;
   
    private static final Log  log              = LogFactory.getLog(JasperAction.class);
   
    public String execute() throws Exception {

        log.debug(“Creating Reporting”);      
        log.debug(reportsList);     
     
        reportsList = (List<TransportBooking>) getSession().get(“reportsList”);
        // Normally we would provide a pre-compiled .jrxml file
        // or check to make sure we don’t compile on every request.
        try {
            JasperCompileManager.compileReportToFile(
                    “F:/programming-tools/apache-tomcat-7.0.2/webapps/web-deploy/transportbooking_template.jrxml”,
                    “F:/programming-tools/apache-tomcat-7.0.2/webapps/web-deploy/transportbooking_template.jasper”);
        } catch (Exception e) {
            e.printStackTrace();
            for(int i = 0; i < e.getStackTrace().length; i++)
            log.debug(e.getStackTrace()[i]);
            return ERROR;
        }

        return SUCCESS;
    }

    public List<TransportBooking> getReportsList() {
        return reportsList;
    }

    public void setReportsList(List<TransportBooking> reportsList) {
        this.reportsList = reportsList;
    }
   

    public void setSession(Map session) {
          this.session = session;
      }

      public Map getSession() {
          return session;
      }
   
   

}

The folder for our web application which I will call web-deploy has the structure:

The web-xml looks like:

<?xml version=”1.0″ encoding=”UTF-8″?>
<web-app id=”struts2-jquery-showcase” version=”2.4″ xmlns=”http://java.sun.com/xml/ns/j2ee&#8221; xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221; xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd”&gt;

    <display-name>PaltrackTransportBookingDemo</display-name>

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

</web-app>

The grid.jsp web page is where are the events take place:

<%@ taglib prefix=”s” uri=”/struts-tags”%>
<%@ taglib prefix=”sj” uri=”/struts-jquery-tags”%>
<%@ taglib prefix=”sjg” uri=”/struts-jquery-grid-tags”%>

<script type=”text/javascript”>
    datePick = function(elem) {
        $(elem).datepicker();
        $(‘#ui-datepicker-div’).css(“z-index”, 2000);
    }
</script>
<s:url id=”remoteurl” action=”json-table” />
    <s:url id=”editurl” action=”edit-transport-booking” />
        <s:url id=”pdfreporturl” action=”jasper” /> 
            <s:url id=”excelreporturl” action=”jasper-excel” />
            <s:url id=”csvreporturl” action=”jasper-csv” />
            <s:url id=”htmlreporturl” action=”jasper-html” />
    <sjg:grid
        id=”transportbookingtable”
        caption=”TransportBooking (Editable/Multiselect)”
        dataType=”json”
        href=”%{remoteurl}”
        pager=”true”
        navigator=”true”
        navigatorSearch=”true”
        navigatorSearchOptions=”{multipleSearch:true}”       
        navigatorAddOptions=”{
            height:280,
            reloadAfterSubmit:true,
            afterSubmit:function(response, postdata) {
                            return isError(response.responseText);
                         }
        }”
        navigatorEdit=”true”
        navigatorEditOptions=”{
            height:280,
            reloadAfterSubmit:true,
            afterSubmit:function(response, postdata) {
                            return isError(response.responseText);
                         }
        }”
        navigatorView=”true”
        navigatorDelete=”true”
        navigatorDeleteOptions=”{
            height:280,
            reloadAfterSubmit:true,
            afterSubmit:function(response, postdata) {
                            return isError(response.responseText);
                         }
        }”
        gridModel=”gridModel”
        rowList=”10,15,20″
        rowNum=”15″
        editurl=”%{editurl}”
        editinline=”false”
        multiselect=”true”
        viewrecords=”true”
    >
        <sjg:gridColumn name=”bookingId”
            index=”bookingId”
            key=”true”
            title=”ID”
            width=”50″
            formatter=”integer”
            sortable=”true”
            search=”true”
            searchoptions=”{sopt:['eq','ne','lt','gt','le','ge']}”
        />
        <sjg:gridColumn
            name=”name”
            index=”name”
            title=”name”
            width=”300″
            sortable=”true”
            editable=”true”
            edittype=”text”
            search=”true”
            searchoptions=”{sopt:['eq','ne','lt','gt','le','ge']}”
        />
        <sjg:gridColumn
            name=”phone”
            index=”phone”
            title=”phone”
            sortable=”true”
            editable=”true”
            edittype=”text”
            search=”true”
            searchoptions=”{sopt:['eq','ne','lt','gt','le','ge']}”
            />
        <sjg:gridColumn
            name=”cellnumber”
            index=”cellnumber”
            title=”cellnumber”
            sortable=”true”
            editable=”true”
            edittype=”text”
            search=”true”
            searchoptions=”{sopt:['eq','ne','lt','gt','le','ge']}”
            /> 
        <sjg:gridColumn
            name=”confirmBy”
            index=”confirmBy”
            title=”confirmBy”
            sortable=”true”
            editable=”true”
            edittype=”text”
            editoptions=”{size: 19, maxlength: 19, dataInit:datePick }”
            formatter=”date”
            formatoptions=”{newformat : ‘d.m.Y H:i’, srcformat : ‘Y-m-d H:i:s’}”
            width=”90″           
            search=”true”
            searchoptions=”{sopt:['eq','ne','lt','gt','le','ge'], dataInit:datePick, attr:{title:’Your Search Date’}}”
            />
        <sjg:gridColumn
            name=”transport”
            index=”transport”
            title=”transport”
            sortable=”true”
            editable=”true”
            edittype=”text”
            search=”true”
            searchoptions=”{sopt:['eq','ne','lt','gt','le','ge']}”
            />
    </sjg:grid>
   
    <br>
    <br>
    <br>
    <br>  
 <div id=”nav”>
      <div class=”hlist ui-widget-header”>
         <ul>
 <li class=”ui-widget-header”><s:a id=”reportlink” href=”%{pdfreporturl}” >PDF Report</s:a></li>
 <li class=”ui-widget-header”><s:a id=”reportlink” href=”%{excelreporturl}” >Excel Report</s:a></li>
 <li class=”ui-widget-header”><s:a id=”reportlink” href=”%{csvreporturl}” >CSV Report</s:a></li>
 <li class=”ui-widget-header”><s:a id=”reportlink” href=”%{pdfreporturl}” >HTML Report</s:a></li>
         </ul>
       </div>
     </div>

Here you can see how to add date pickers and filters for multiple criteria filters. Please not that I borrowed the theme from the showcase of the JQuery examples at http://www.weinfreund.de/struts2-jquery-showcase/index.action.

The end result is as follows:

The relevant libraries needed to build the project:

Enjoy! If you have any queries or would like more source code please email me and I can email you the source code zipped.

Posted in Uncategorized | 15 Comments

Struts 2 and JQGrid – An alternative to other visually rich web applications

Happy New Year to one and all. My first blog for the New Year.  Struts 2 and JQGrid offer an elegant alternative to changing languages or trying other frameworks that involve other languages. Imagine if you have inherited an application that was written in Java and used maybe Struts 2? Even if it didn’t involve Struts, migrating an existing project in Java to Struts 2 is easier than migrating an existing application to another language. We can reuse the expertise of the seasoned developers that are already present in team. Why re-train?

JQGrid offers a comprehensive toolset that leverages the power of Ajax and lends this power to Struts 2 via the Struts 2 JQGrid. Visit  http://www.jgeppert.com/2010/01/new-showcase-for-the-jqgrid-feature-in-struts2-jquery-plugin-is-available/ I admit this is rapidly evolving package that we don’t hear much of but can be useful.

it is now an accepted fact that JavaScript plays an important part in web applications it allows us to create rich applications that have attractive visual effects. This is the power JQGrid lends to especially Java developers that don’t want to move much out of their Java realm.

In my next blog I plan to build an application that will illustrate the various features of the JQGrid toolset. Indeed we will explore some of the lesser known concepts that add amazing features to filtering, sorting and searching tabular data.

Yes there are other languages other frameworks but if your team is skilled in Java wouldn’t it be wise to invest in enhancing the skills and utilizing the existing abilities than to retrain in completely new languages.

Then of course there is the “rapid part” and learning curve. If the extra features of the JQGrid require a greater learning curve than learning another framework from scratch then this might not be the best. My perspective is that the learning curve for JQGrid is actually very gentle. However the last word lies with the team.

A Struts 2 JQgrid application can be setup in such a way that the code will have alot of reuseable components. Making dealing with tabular data throughout the application easier and seems to be faster than the new code generators out there for web applications.

Lastly in the application i present in my next blog, I will add an important part that is not by default offered in the JQGrid plugin, this is creating reports. I use an interesting yet powerful alternative for this.

With these thoughts in mind I take my leave until next time.

Posted in Uncategorized | 1 Comment

Picking Dates in Struts 2 and JQGrid

I have spent sometime analysing the power of Struts 2 and JQGrid. In a time when so many frameworks are out there, so many projects, some of which perform code generation, the question is can Struts 2 still have a place in the new world, the new era that has seen the rise of web technologies with mouth watering graphics and tantalizing visual effects?

I am happy to say that yes it can. Within the JQGrid Struts 2 is a framework that has the capability to make it through and past 2010 into the second decade of this new century that has dawned upon us.

Today I write about dates and date picking in the Struts 2 JQGrid plugin. The reason being there seems to be, to my knowledge, no clear explanation on this. In my next post I will give a full tutorial on the use of JQGrid and more comprehensive coverage on this wonderful plugin.

We want to be able to have a date picker in the Add Record screen. In the picture below confirmBy is a date field and when we click on it:

Also when we edit a record, on the Edit Record screen, we click on the date field we have:

The settings for this are as follows. First in the sjg:GridColumn we have:

Where the datePick function will be:

There we are. We have added date picking functionality in the Add Record screen and the Edit Record screen.

 

Posted in Computers and Internet, Java programming, JavaScript, Uncategorized | Leave a comment