Forum Stats

  • 3,839,827 Users
  • 2,262,538 Discussions
  • 7,901,064 Comments

Discussions

Ejb with rest service to upload / update blob

DLopez
DLopez Member Posts: 278
edited Sep 3, 2015 5:46AM in JDeveloper and ADF

Hi,

I have successfully use a rest service to present an image saved in my DB as a BLOB, but now I have to do the opposite, upload one image and save it as blob, replacing the older one or adding a new one.

I thought that I could implement the same way that I use to update other data like strings, numbers and dates:

    @POST
    @Consumes("application/xml")
    @Path("/merge/")
    public Response update(Customer customer) {
        
        Customer persistedCustomerRecord = SessionBean.getCustomerFindByRecId(customer.getRecid()).get(0);
        if (persistedCustomerRecord != null) {
        
            persistedCustomerRecord.setFname(customer.getFname());
            persistedCustomerRecord.setMname(customer.getMname());
            persistedCustomerRecord.setName(customer.getName());
            persistedCustomerRecord.setAnniversdate(customer.getAnniversdate());
      
            SessionBean.mergeCustomer(persistedCustomerRecord);
        } else {


            throw new ResourceNotFoundException("The employee resource with the id " + customer.getRecid() + "could not be found");
        }
        return Response.ok().build();
    }

but when I test my service the input field for my memo appears has base64Binary and there isn't a 'button' like calendar to select the file.

With this in mind I guess I have to somehow allow the upload, selecting the file and convert it as byte[], since it's the type of data defined by EJB when creating the Entity from Table.

Am I right?

How can I accomplish this?

I'm using jdev 12c and EJB

Thanks

Best Answer

  • DLopez
    DLopez Member Posts: 278
    edited Sep 3, 2015 5:46AM Answer ✓

    Fixed.

    My service now looks like

        @POST
        @Consumes("application/xml")
        @Path("/merge/")
        public Response updatePhoto(Memos memo) {
            System.out.println("entrei " + memo.getSourceid());
            //find the employee record
            Memos persistedMemosRecord = SessionBean.getMemosUploadRecord(memo.getSourceid()).get(0);
            if (persistedMemosRecord != null) {
                System.out.println("no if, sourceid = " + persistedMemosRecord.getSourceid() + persistedMemosRecord.getRecid());
                //update employee object
                System.out.println("size " + memo.getThememo().length);
                persistedMemosRecord.setThememo(memo.getThememo());
                //persist the change
                SessionBean.mergeMemos(persistedMemosRecord);
            } else {
    
    
                throw new ResourceNotFoundException("The employee resource with the id " + memo.getRecid() + "could not be found");
            }
            return Response.ok().build();
        }
    

    The client xsd

    <?xml version="1.0" encoding="UTF-8" ?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns="http://www.example.org"
                targetNamespace="http://www.example.org" elementFormDefault="qualified">
        <xsd:element name="photo">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="thememo" type="xsd:base64Binary"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>
    

    And the bean of the jsf page

        public void fileUploaded(ValueChangeEvent event) {
            UploadedFile file = (UploadedFile) event.getNewValue();
            if (file != null) {
                BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
                AttributeBinding attr = (AttributeBinding) bindings.getControlBinding("recid");
                String sourceid = attr.getInputValue().toString();
    
    
                FacesContext context = FacesContext.getCurrentInstance();
                FacesMessage message = new FacesMessage("Successfully uploaded file " + file.getFilename() + " (" + file.getLength() + " bytes)");
                context.addMessage(event.getComponent().getClientId(context), message);
                DCBindingContainer bc = (DCBindingContainer) BindingContext.getCurrent().getCurrentBindingsEntry();
                OperationBinding op = bc.getOperationBinding("updatePhoto");
    
    
                try {
                    System.out.println("################# fileUpload op " + op);
                    byte[] buffer = readFully(file.getInputStream());
                    String encodedStr = new sun.misc.BASE64Encoder().encode(buffer);
                    if (op != null) {
                        Map tempMap = new HashMap();
    
    
                        tempMap.put("thememo", encodedStr);
                        tempMap.put("sourceid", sourceid);
                        op.getParamsMap().put("memos", tempMap);
                        System.out.println("################ ja guardei no map str64 " + op.toString());
                        op.execute();
                    }
                } catch (IOException e) {
                    System.out.println(e);
                }
            }
        }
    
    
        /**
         *  Method to convert the InputStream to ByteArray
         */
    
    
        public byte[] readFully(InputStream input) throws IOException {
            byte[] buffer = new byte[8192];
            int bytesRead;
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            while ((bytesRead = input.read(buffer)) != -1) {
                output.write(buffer, 0, bytesRead);
            }
            return output.toByteArray();
        }
    

    fileUpload is associated to a inputFile componente

    <af:panelFormLayout id="pfl3" binding="#{backingBeanScope.backing_pages_updateCustomer.pfl3}">
      <f:facet name="footer"/>
      <af:inputFile label="Photo" id="if1" binding="#{backingBeanScope.backing_pages_updateCustomer.if1}" valueChangeListener="#{backingBeanScope.backing_pages_updateCustomer.fileUploaded}" autoSubmit="true"/>
      <af:button text="updatePhoto" disabled="#{!bindings.updatePhoto.enabled}" id="b3" binding="#{backingBeanScope.backing_pages_updateCustomer.b3}" partialTriggers="if1" actionListener="#{bindings.updatePhoto.execute}" visible="false"/>
    </af:panelFormLayout>
    

    Thanks for your help

Answers

  • kdario
    kdario Member Posts: 3,531 Silver Crown
    edited Aug 19, 2015 1:00PM
    but when I test my service the input field for my memo appears has base64Binary and there isn't a 'button' like calendar to select the file.
    

    So how do you test this?

    If this is some web service tester, this is probably expected behavior.

    With this in mind I guess I have to somehow allow the upload, selecting the file and convert it as byte[], since it's the type of data defined by EJB when creating the Entity from Table.
    How can I accomplish this?
    

    So what you use as real front-end? adf page? something else?

    Dario

  • DLopez
    DLopez Member Posts: 278
    edited Aug 19, 2015 1:15PM

    For now I was trying to use Http Analyser of the service, without client component, but I guess that for this it won't work.

    My idea is to add a InputFile in a jsf page so I can upload the file, picture, and save it.

  • kdario
    kdario Member Posts: 3,531 Silver Crown
    edited Aug 19, 2015 1:30PM
    For now I was trying to use Http Analyser of the service, without client component, but I guess that for this it won't work.
    

    Well, you can use some free online service to convert file to base64 (or you can code utility app for this)

    Dario

  • KKRN
    KKRN Member Posts: 81
    edited Aug 20, 2015 1:05AM

    HI DLopez,

    I've a solution for workaround process, if possible u can try for this:

    1) First step u can put a button for Browse.. ok then browse the image

    2)Add one new filed in DB as CLOB domain

    3) Then Image convert into bytes

    4) Then the Bytes value is stored on String which is added new column in DB

    5) While retrieving the Image make sure the respected VO new column changed to String data type

    6) Using this string u can retrieve the image which you have browsed & displayed

  • DLopez
    DLopez Member Posts: 278
    edited Aug 20, 2015 5:41AM

    Thanks Dario,

    I start doing as you said, but I don't know yet why I'm getting the 200 Ok and when I'll check the DB the new image won't appear in the place of the old one.

    With strings, dates and other types of data, the method I'm using works (presented in the original post).

    Thanks for your reply KKRN, in this case I'm not using VO, what I have is a rest service, using also EJB, to transfer data between client and database. What I'm doing is creating a service that, now, allows me to upload an image and save it in my DB, replacing the older one.

    Any idea of what it could be?

    Thanks

    UPDATE:

    Found my mistake, I was calling the wrong function so the record I wanted to update was not.

  • DLopez
    DLopez Member Posts: 278
    edited Sep 3, 2015 5:46AM Answer ✓

    Fixed.

    My service now looks like

        @POST
        @Consumes("application/xml")
        @Path("/merge/")
        public Response updatePhoto(Memos memo) {
            System.out.println("entrei " + memo.getSourceid());
            //find the employee record
            Memos persistedMemosRecord = SessionBean.getMemosUploadRecord(memo.getSourceid()).get(0);
            if (persistedMemosRecord != null) {
                System.out.println("no if, sourceid = " + persistedMemosRecord.getSourceid() + persistedMemosRecord.getRecid());
                //update employee object
                System.out.println("size " + memo.getThememo().length);
                persistedMemosRecord.setThememo(memo.getThememo());
                //persist the change
                SessionBean.mergeMemos(persistedMemosRecord);
            } else {
    
    
                throw new ResourceNotFoundException("The employee resource with the id " + memo.getRecid() + "could not be found");
            }
            return Response.ok().build();
        }
    

    The client xsd

    <?xml version="1.0" encoding="UTF-8" ?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns="http://www.example.org"
                targetNamespace="http://www.example.org" elementFormDefault="qualified">
        <xsd:element name="photo">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="thememo" type="xsd:base64Binary"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>
    

    And the bean of the jsf page

        public void fileUploaded(ValueChangeEvent event) {
            UploadedFile file = (UploadedFile) event.getNewValue();
            if (file != null) {
                BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
                AttributeBinding attr = (AttributeBinding) bindings.getControlBinding("recid");
                String sourceid = attr.getInputValue().toString();
    
    
                FacesContext context = FacesContext.getCurrentInstance();
                FacesMessage message = new FacesMessage("Successfully uploaded file " + file.getFilename() + " (" + file.getLength() + " bytes)");
                context.addMessage(event.getComponent().getClientId(context), message);
                DCBindingContainer bc = (DCBindingContainer) BindingContext.getCurrent().getCurrentBindingsEntry();
                OperationBinding op = bc.getOperationBinding("updatePhoto");
    
    
                try {
                    System.out.println("################# fileUpload op " + op);
                    byte[] buffer = readFully(file.getInputStream());
                    String encodedStr = new sun.misc.BASE64Encoder().encode(buffer);
                    if (op != null) {
                        Map tempMap = new HashMap();
    
    
                        tempMap.put("thememo", encodedStr);
                        tempMap.put("sourceid", sourceid);
                        op.getParamsMap().put("memos", tempMap);
                        System.out.println("################ ja guardei no map str64 " + op.toString());
                        op.execute();
                    }
                } catch (IOException e) {
                    System.out.println(e);
                }
            }
        }
    
    
        /**
         *  Method to convert the InputStream to ByteArray
         */
    
    
        public byte[] readFully(InputStream input) throws IOException {
            byte[] buffer = new byte[8192];
            int bytesRead;
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            while ((bytesRead = input.read(buffer)) != -1) {
                output.write(buffer, 0, bytesRead);
            }
            return output.toByteArray();
        }
    

    fileUpload is associated to a inputFile componente

    <af:panelFormLayout id="pfl3" binding="#{backingBeanScope.backing_pages_updateCustomer.pfl3}">
      <f:facet name="footer"/>
      <af:inputFile label="Photo" id="if1" binding="#{backingBeanScope.backing_pages_updateCustomer.if1}" valueChangeListener="#{backingBeanScope.backing_pages_updateCustomer.fileUploaded}" autoSubmit="true"/>
      <af:button text="updatePhoto" disabled="#{!bindings.updatePhoto.enabled}" id="b3" binding="#{backingBeanScope.backing_pages_updateCustomer.b3}" partialTriggers="if1" actionListener="#{bindings.updatePhoto.execute}" visible="false"/>
    </af:panelFormLayout>
    

    Thanks for your help

This discussion has been closed.