primeFaces fails to upload file to db

2019-09-12 12:20发布

问题:

I am trying to upload a file (picture) which is part of a Product object to a database. The file upload is successful according to the jsf confirmation. However, when persisting Product the persistence is completed successfully without the picture. The server is not returning any stack.

This is my form (simplified):

<h:form enctype="multipart/form-data">
                <h1><h:outputText value="Create New Product"/></h1>
                <h:panelGrid columns="2">

                    <h:outputLabel value="Name:" for="name" />
                    <h:inputText id="name" value="#{productController.product.name}" title="Name" />

                    <h:outputLabel value="Description:" for="description" />
                    <h:inputText id="description" value="#{productController.product.description}" title="Description" />

                    <h:outputLabel value="Price:" for="price" />
                    <h:inputText id="price" value="#{productController.product.price}" title="Price" />                     

                    <h:outputLabel value="Category:" for="category_fk" />
                    <h:selectOneMenu id="category_fk" value="#{productController.product.category_fk}" 
                                     converter="#{categoryConverter}" title="Category_fk" >                        
                        <f:selectItems value="#{productController.categoryList}" var="prodCat"
                                       itemValue="#{prodCat}" itemLabel="#{prodCat.name}"/>
                    </h:selectOneMenu>                                    

                    <p:fileUpload fileUploadListener="#{productController.handleFileUpload}" update="msg" auto="true" />                                                
                    <p:growl id="msg" showDetail="true"/>


                    <h:inputHidden id="dateAdded" value="#{productController.product.dateAdded}">
                        <f:convertDateTime pattern="yyyy/MM/dd HH:mm:ss" />
                    </h:inputHidden>

                </h:panelGrid>

                <h:commandButton value="Create Product" action="#{productController.doCreateProduct()}"/>

            </h:form>

This the product Controller (Simplified):

@ManagedBean
@RequestScoped
public class ProductController {

    @EJB
    private ProductEJB productEjb;
    @EJB
    private CategoryEJB categoryEjb;

    private Product product = new Product();
    private List<Product> productList = new ArrayList<Product>();

    private Category category;
    private List<Category> categoryList = new ArrayList<Category>();

    // -------------------------------------------------------- Business Methods
    public String doCreateProduct()
    {

        product = productEjb.createProduct(product);
        productList = productEjb.findAllProducts();
        return "listProduct?faces-redirect=true";
    }


    public String doDeleteProduct()
    {
        productEjb.deleteProduct(product);        
        return "listProduct?faces-redirect=true";
    }

    public String cancelDeleteAction()
    {
        return "listProduct?faces-redirect=true";
    }

        // Update product listing
        public void preRenderView()
        {
            if(product == null)
            {
                product = new Product();                
            }            
        }

        public String doUpdateProduct()
        {
            if(product.getProduct_id() != 0)
            {
                productEjb.updateProduct(product);                
            }
            else
            {
                productEjb.createProduct(product);
            }

            //addFlashMessage("Product " + product.getName() + " (" + product.getProduct_id() + ") has been updated");

            return "listProduct?faces-redirect=true";
        }

        public void handleFileUpload(FileUploadEvent event)
        {
            byte[] uploadedFile = new byte[event.getFile().getContents().length];
            System.arraycopy(event.getFile().getContents(), 0, uploadedFile, 0, event.getFile().getContents().length);
            product.setImageFile(uploadedFile);

            FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + "is uploaded.");        
            FacesContext.getCurrentInstance().addMessage(null, msg);
        }

    @PostConstruct
    public void init()
    {
        categoryList = categoryEjb.findAllCategory();
        productList = productEjb.findAllProducts();        
    }

This is the product entity(Simplified):

@Entity
@NamedQueries({
    @NamedQuery(name="findAllProducts", query = "SELECT p from Product p")

})
public class Product implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Id @GeneratedValue(strategy= GenerationType.AUTO)
    private int product_id;
    private String name;
    private String description;
    @Lob
    @Column(name="imageFile")
    protected byte[] imageFile;
    private Float price;
    @Temporal(TemporalType.TIMESTAMP)
    private Date dateAdded;        
    @ManyToOne
    private Category category_fk;
    @OneToOne(mappedBy = "product_fk")
    private SaleDetails saleDetails_fk;

SOLUTION: I changed the scope of the managed bean to:

@ViewScope

回答1:

Fileupload happens in a first request.

When form is submited with the input data, a new 2nd request will be initiated. A new requestScoped ManagedBean will be created, that doesnt know about the previous fileupload.

To allow the two requests to share the same Managedbean, Change the scope to:

@ViewScoped