0

In a spring mvc application that utilizes hibernate and jpa, I have a form that needs to store a document including metadata about the document such as the current date when the form is submitted. I have the model, controller, and jsp all set up, but when it runs, the create or add jsp is returned when the user clicks on the button to submit a document to the database. The error indicates that the problem is that the code is not handling the conversion from String to Blob. I HAVE NOTED THE LOCATION IN THE processCreationForm() METHOD WHERE THE CODE IS RETURNING THE createOrUpdateDocumentForm.jsp INSTEAD OF REDIRECTING TO THE LIST JSP AND I HAVE INCLUDED THE ERROR MESSAGE AT THE BOTTOM OF THIS POSTING.

How can I change my code below so that document is saved to the database when the user clicks on the submit button?

Here is my createOrUpdateDocumentForm.jsp:

<body>
<script>
    $(function () {
        $("#created").datepicker({ dateFormat: 'yy/mm/dd'});
    });
</script>
<div class="container">
    <jsp:include page="../fragments/bodyHeader.jsp"/>
    <c:choose>
        <c:when test="${document['new']}">
            <c:set var="method" value="post"/>
        </c:when>
        <c:otherwise>
            <c:set var="method" value="put"/>
        </c:otherwise>
    </c:choose>

    <h2>
        <c:if test="${document['new']}">New </c:if>
        Document
    </h2>

    <form:form modelAttribute="document" method="${method}"
               class="form-horizontal">
        <div class="control-group" id="patient">
            <label class="control-label">Patient </label>

            <c:out value="${document.patient.firstName} ${document.patient.lastName}"/>
        </div>
        <petclinic:inputField label="Name" name="name"/>
        <petclinic:inputField label="Description" name="description"/>
        <div class="control-group">
            <petclinic:selectField name="type" label="Type " names="${types}" size="5"/>
        </div>
        <td><input type="file" name="content" id="content"></input></td>
        <div class="form-actions">
            <c:choose>
                <c:when test="${document['new']}">
                    <button type="submit">Add Document</button>
                </c:when>
                <c:otherwise>
                    <button type="submit">Update Document</button>
                </c:otherwise>
            </c:choose>
        </div>
    </form:form>
    <c:if test="${!document['new']}">
    </c:if>
    <jsp:include page="../fragments/footer.jsp"/>
</div>
</body>

Here are the relevant parts of the controller:

@RequestMapping(value = "/patients/{patientId}/documents/new", method = RequestMethod.GET)
public String initCreationForm(@PathVariable("patientId") int patientId, Map<String, Object> model) {
    Patient patient = this.clinicService.findPatientById(patientId);
    Document document = new Document();
    patient.addDocument(document);
    model.put("document", document);
    return "documents/createOrUpdateDocumentForm";
}

@RequestMapping(value = "/patients/{patientId}/documents/new", method = RequestMethod.POST)
public String processCreationForm(@ModelAttribute("document") Document document, BindingResult result, SessionStatus status) {
    document.setCreated();
    //THE FOLLOWING LINE PRINTS OUT A VALID DATE FOR document.getCreated()
    System.out.println("document.getCreated() is: "+document.getCreated());
    new DocumentValidator().validate(document, result);
    if (result.hasErrors()) {
        System.out.println("result.getFieldErrors() is: "+result.getFieldErrors());
        //THIS IS BEING RETURNED BECAUSE result.getFieldErrors() RETURNS WHAT IS BEING  
        //SHOWN AT THE BOTTOM OF THIS POSTING, BELOW  
        return "documents/createOrUpdateDocumentForm";
    }
    else {
        this.clinicService.saveDocument(document);
        status.setComplete();
        return "redirect:/patients?patientID={patientId}";
    }
}

And here is the the model, which are parts of Document.java:

@Entity
@Table(name = "documents")
public class Document {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "client_id")
    private Patient patient;

    @ManyToOne
    @JoinColumn(name = "type_id")
    private DocumentType type;

    @Column(name="name")
    private String name;

    @Column(name="description")
    private String description;

    @Column(name="filename")
    private String filename;

    @Column(name="content")
    @Lob
    private Blob content;

    @Column(name="content_type")
    private String contentType;

    @Column(name = "created")
    private Date created;

    public Integer getId(){return id;}
    public void setId(Integer i){id=i;}

    protected void setPatient(Patient patient) {this.patient = patient;}
    public Patient getPatient(){return this.patient;}

    public void setType(DocumentType type) {this.type = type;}
    public DocumentType getType() {return this.type;}

    public String getName(){return name;}
    public void setName(String nm){name=nm;}

    public String getDescription(){return description;}
    public void setDescription(String desc){description=desc;}

    public String getFileName(){return filename;}
    public void setFileName(String fn){filename=fn;}

    public Blob getContent(){return content;}
    public void setContent(Blob ct){content=ct;}

    public String getContentType(){return contentType;}
    public void setContentType(String ctype){contentType=ctype;}

    public void setCreated(){created=new java.sql.Date(System.currentTimeMillis());}
    public Date getCreated() {return this.created;}

    @Override
    public String toString() {return this.getName();}
    public boolean isNew() {return (this.id == null);}

}

The above code compiles, but when the user presses the submit button after entering the information to upload a document, the same add or update form is returned instead of redirecting to the summary page. This indicates from the controller method above that result.haserrors is true even though none of the errors checked for by system.out.println are true. The eclipse console does not show an error. However result.getFieldErrors() prints out the following:

[
Field error in object 'document' on field 'content': 
rejected value [mydocname.txt]; 
codes [typeMismatch.document.content,typeMismatch.content,typeMismatch.java.sql.Blob,typeMismatch]; 
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: 
codes [document.content,content]; 
arguments []; default message [content]]; 
default message 
[
Failed to convert property value of type 'java.lang.String' to required type 'java.sql.Blob' for property 'content'; 
nested exception is java.lang.IllegalStateException: 
Cannot convert value of type [java.lang.String] to required type [java.sql.Blob] for property 'content': 
no matching editors or conversion strategy found
]
]
CodeMed
  • 9,527
  • 70
  • 212
  • 364

1 Answers1

2

First of all Your form is missing the tag enctype="multipart/form- data", If it not still working you may consider using the MultipartFile interface

UPDATE

You can read the spring documentation, it is really straightforward . Now, to apply it in your situation you can follow this tutorial : Saving/Retreving BLOB object in Spring 3 MVC and Hibernate

UdayKiran Pulipati
  • 6,579
  • 7
  • 67
  • 92
storm_buster
  • 7,362
  • 18
  • 53
  • 75
  • Thank you. Do you have further specific step by step instructions, if I tell you that adding enctype="multipart/form-data" results in an error message stating: java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured? – CodeMed Dec 11 '13 at 02:10
  • Thank you, but that does not really help. I found the additional required dependencies and I did a maven update, but now the problem is that the part of the code above that uses a SessionFractory object to manage the blob is returning a null session. I framed it in a new question to keep things simple, but the same ultimate problem is how to get a blob into a database. Do you have a solution? Here is the link: http://stackoverflow.com/questions/20509801/calling-session-object-from-spring-petclinic-using-jpa – CodeMed Dec 11 '13 at 03:14
  • Will reply there about your sessionfactory, this one could be considered as solved? – storm_buster Dec 11 '13 at 04:42
  • I put a large bounty on a related question. Would you mind looking at the related question and submitting an answer? I will award the large bounty to the person who provides a working solution with an explanation. Here is the link: http://stackoverflow.com/questions/20586865/document-not-saving-in-spring-jpa-document-manager-application – CodeMed Dec 17 '13 at 00:23