1

I have been working on struts for a long time.

I am simulating programmatic validations and conversion errors in an application using Struts 2.

In my application I have a model class called Product which is as shown below:

public class Product {

private String productId;
private String productName;
private int price;

public Product() {}

public Product(String productId, String productName, int price) {
    this.productId = productId;
    this.productName = productName;
    this.price = price;
}

public String getProductId() {
    return productId;
}

public void setProductId(String productId) {
    System.out.println("Product.setProductId() : '"+productId+"'");
    this.productId = productId;
    System.out.println("This.pid : "+this.productId);
}

public String getProductName() {
    return productName;
}

public void setProductName(String productName) {
    System.out.println("Product.setProductName() : '"+productName+"'");
    this.productName = productName;
}

public int getPrice() {
    return price;
}

public void setPrice(int price) {
    System.out.println("Product.setPrice() : '"+price+"'");
    this.price = price;
}

}

I have jsp called ProductForm.jsp where I ask user to enter product info like below:

<%@taglib uri="/struts-tags" prefix="s" %>
<html>
<head>
    <title>Add Product Form</title>
    <style type="text/css">@import url(css/main.css);</style>
</head>
<body>
    <div id="global">
        <h3>Add a product</h3>
        <s:form method="post" action="Product_Save.action">
            <s:textfield label="Id" key="productId"/>
            <s:textfield label="Name" key="productName"/>
            <s:textfield label="Price" key="price"/>
            <s:submit value="Add Product"/>
        </s:form>
        <s:debug/>
    </div>
</body>
</html>

If user clicks on Add Productbutton by giving correct info data will be saved to database according to normal flow which is configured in struts.xml which is as below:

<!DOCTYPE struts PUBLIC 
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="product_module" extends="struts-default">

    <action name="Product_Input">
        <result>/jsp/ProductForm.jsp</result>
    </action>

    <action name="Product_Save" class="com.way2learnonline.ui.ProductAction">
        <result name="success">/jsp/ProductDetails.jsp</result>
        <result name="input">/jsp/ProductForm.jsp</result>
        <param name="test">MyTest</param>
    </action>

</package>

</struts>

My Action class is ProductAction which is as shown below:

public class ProductAction extends ActionSupport implements ModelDriven<Product>{

private static final long serialVersionUID = 1L;

private Product product;

private String test;

public ProductAction() {}

public String execute(){
    DatabaseManager databaseManager=new DatabaseManager();
    databaseManager.write(product);
    return Action.SUCCESS;
}

@Override
public void validate() {

    System.out.println("p : "+product.getProductId());
    if(product.getProductId().trim().equals("")){
        addFieldError("productId", "Product Id should be present");
    }
    if(product.getPrice()<=0){
        addFieldError("price", getText("price.negative"));
    }
}

@Override
public Product getModel() {
    product=new Product();
    return product;
}

public void setTest(String test) {
    this.test = test;
}

public String getTest() {
    return test;
}
}

If we give invalid data like price less than or equal to zero or productId is empty then validation will be triggered.

If we give alphabets in price field then conversion error will be triggered.

But If I give alphabets in price field then my product object all variables are becoming nulls while it goes to validate() method, which is resulting null pointer exception in validate() method when I try to access productId from product object of ProductAction class.

Here why is my product object variables of ProductAction class are becoming null if I give alphabets in price field in ProductForm.jsp.

Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
Jagadeesh
  • 862
  • 7
  • 23
  • According to [this](http://stackoverflow.com/a/23450365/1654265), it should not. There must be something very strange going on here. Which S2 version ? Can you try removing the constructor with parameters ? Nice question BTW – Andrea Ligios Sep 11 '15 at 08:44
  • @Aleksandr M I am not able to understand what do you mean by "I doubt this code will work at all having action="Product_Save.action" in the " – Jagadeesh Sep 11 '15 at 08:59
  • Well it seems it do work, but if you are using S2 tags it is better not to put an extension `.action` to action name. – Aleksandr M Sep 11 '15 at 09:05
  • @ Aleksandr M There is no issue with bacause even after did changes according to you also same null pointer exception is coming – Jagadeesh Sep 11 '15 at 09:08
  • @ Aleksandr M If you want I will upload entire source code so that you can run it and have a good idea on what went wrong – Jagadeesh Sep 11 '15 at 09:09
  • 1
    @All I got answer to my question here the thing is Struts2 calls getModel() method before conversion error as well as before validation. In my get model method I am returning new Product() object each time. So my data is populated into for Product object. Then Struts2 calls getModel() method one more time just before validation, where again I am returning new Product() so validation is happening on second product object where there is no data set. Thanks all thanks for your valuable time for me. Any way good luck guys. – Jagadeesh Sep 11 '15 at 09:19
  • You can try w/o modeldriven. – Aleksandr M Sep 11 '15 at 09:25

1 Answers1

1

Put the model initialization in the declaration, not in the getter:

private Product product = new Product();

@Override
public Product getModel() {
    return product;
}
Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243