Search code examples
javaazurevaadinazure-storageazure-blob-storage

How to implement azure-storage into vaadin framework


I am trying to upload a file into Azure Blob. and I am trying to achieve through Upload in vaadin framework. Vaadin Version : 6.7.8

I am able to develop a code for uploading the file into azure blob.

My Problem Statement Lies below :

  • I have written a class UploadToBlob.java to upload a file into azure blob.
  • If I run the class UploadToBlob.java indivually (ran from eclipse run as java application), I am able to upload the file into azure blob.
  • If I create a object of the UploadToBlob class in my other class[ModifyComplaintComponent.java], storageAccount = CloudStorageAccount.parse(storageConnectionString); is not getting execute.

Below is the UploadToBlob.java code:

    package com.---.trs.scms.ui.components;

import com.microsoft.azure.storage.CloudStorageAccount;
import com.microsoft.azure.storage.StorageCredentials;
import com.microsoft.azure.storage.blob.CloudBlobContainer;

public class UploadToBlob {

    public static void main(String[] args) {

        try {

            final String storageConnectionString = "DefaultEndpointsProtocol=https;AccountName=abcd;AccountKey=bmiA7+****==;EndpointSuffix=core.windows.net";
            System.out.println("---I am getting called Main-1 ");

            CloudStorageAccount storageAccount;

            storageAccount = CloudStorageAccount.parse(storageConnectionString);

            com.microsoft.azure.storage.blob.CloudBlobClient blobClient = storageAccount.createCloudBlobClient();

            CloudBlobContainer container = blobClient.getContainerReference("container2");

            container.createIfNotExists();

            String filePath = "C:\\Users\\----\\Desktop\\Timesheet - 19th Aug,2019.pdf";

            com.microsoft.azure.storage.blob.CloudBlockBlob blob = container.getBlockBlobReference("Timesheet.pdf");

            java.io.File source = new java.io.File(filePath);

            java.io.FileInputStream fileInputStream = new java.io.FileInputStream(source);

            blob.upload(fileInputStream, source.length());

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

For now , I am passing manual file PATH as above to upload in azure blob, as I told above , this class is getting called till the line of code System.out.println("---I am getting called Main-1 ");

Here is the ModifyComplaintComponent code from where I am calling UploadToBlob.java:

import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Upload;

public class ModifyComplaintComponent extends CustomComponent {


//other component  code which I haven't pasted here
    private Upload uploadnew;

    try {
            System.out.println("------Inside try block-----------");
            UploadToBlob fileReceiver= new UploadToBlob ();

            uploadnew = new Upload("Upload a file", fileReceiver);

            uploadnew.setReceiver(fileReceiver);
            uploadnew.addListener(fileReceiver);

            System.out.println("------end of try block-----------");
        }  catch (Exception e) {
            System.out.println("------catch block-----------");
            e.printStackTrace();

        } 

        HorizontalLayout hlayout = new HorizontalLayout();
        hlayout.setSpacing(true);
        hlayout.addComponent(uploadnew);

}

The Reason why I have given a manual file path in my UploadToBlob code is because I firstly wanted to make this code called from ModifyComplaintComponent class.

Secondly when I try to browse the file , and file gets selected but when I click on upload , I get NullPointerException On Vaadin Upload UI Part and even if i selected the file , UI says "no file choosen"

The challenge I am facing is If I run the Upload.java file individually I am able to upload static file into azure blob , but I wanted to browse and upload a file in vaadin framework into azure blob storage.


Solution

  • Firstly, Upload is a Component of Vaadin. You should not create your own Upload class.

    Secondly, the public static main method is an entrance where your program starts. If you want to use a method of a class, you need to explicitly invoke it.

    TheClassName.MethodName(...) // For static method
    new TheClassName(...).MethodName(...) //For non-static method
    

    Thirdly, I did some tests, the following is a successful sample. Two classes will be created:


    Class UploadReceiver

    This class implements the Receiver interface and some listeners.

    import com.microsoft.azure.storage.CloudStorageAccount;
    import com.microsoft.azure.storage.StorageException;
    import com.microsoft.azure.storage.blob.CloudBlobClient;
    import com.microsoft.azure.storage.blob.CloudBlobContainer;
    import com.microsoft.azure.storage.blob.CloudBlockBlob;
    import com.vaadin.ui.Upload;
    import org.springframework.stereotype.Component;
    
    import java.io.OutputStream;
    import java.net.URISyntaxException;
    import java.security.InvalidKeyException;
    
    @Component
    public class UploadReceiver implements Upload.Receiver, Upload.StartedListener, Upload.SucceededListener, Upload.ProgressListener {
        // Storage account connection string.
        public static String conn = "DefaultEndpointsProtocol=https;AccountName=stora***789;AccountKey=G3***w==;EndpointSuffix=core.windows.net";
    
        @Override
        public OutputStream receiveUpload(String filename, String mimeType) {
            System.out.println("Uploading -> " + mimeType + " ; File name -> " + filename);
            return GetOutputStream("vaadin",filename);
        }
    
        @Override
        public void uploadStarted(Upload.StartedEvent startedEvent) {
            System.out.println("Upload started!");
        }
    
        @Override
        public void uploadSucceeded(Upload.SucceededEvent succeededEvent) {
            System.out.println("Upload succeeded!");
        }
    
    
        public OutputStream GetOutputStream(String container, String blob){
            OutputStream outputStream = null;
            try{
                CloudStorageAccount storageAccount = CloudStorageAccount.parse(conn);
                CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
                CloudBlobContainer blobContainer = blobClient.getContainerReference(container);
                CloudBlockBlob cloudBlockBlob = blobContainer.getBlockBlobReference(blob);
                outputStream = cloudBlockBlob.openOutputStream();
            } catch (StorageException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
            return outputStream;
        }
    
        @Override
        public void updateProgress(long readBytes, long contentLength) {
            System.out.println("Progress: readBytes -> " + readBytes + " ; contentLength -> " + contentLength);
        }
    }
    

    Class MainUI

    This is the UI page. I just add an upload component.

    import com.vaadin.server.VaadinRequest;
    import com.vaadin.spring.annotation.SpringUI;
    import com.vaadin.ui.Alignment;
    import com.vaadin.ui.UI;
    import com.vaadin.ui.Upload;
    import com.vaadin.ui.VerticalLayout;
    import org.springframework.beans.factory.annotation.Autowired;
    
    @SpringUI
    public class MainUI extends UI {
    
        private VerticalLayout layout;
        private Upload upload;
    
        private UploadReceiver uploadReceiver;
    
        @Autowired
        public MainUI(UploadReceiver uploadReceiver){
            this.uploadReceiver = uploadReceiver;
        }
    
        @Override
        protected void init(VaadinRequest vaadinRequest) {
    
            // Set layout
            layout = new VerticalLayout();
            layout.setDefaultComponentAlignment(Alignment.MIDDLE_CENTER);
            setContent(layout);
    
    
            // Add upload
            upload = new Upload("Upload a file", uploadReceiver);
            upload.addStartedListener(uploadReceiver);
            upload.addSucceededListener(uploadReceiver);
            upload.addProgressListener(uploadReceiver);
            layout.addComponent(upload);
        }
    }
    
    

    Result: After I clicked the upload button and chose a file to upload, I could get the following outputs from console:

    enter image description here

    And, by checking the storage account with Storage Explorer, I could see that the file was successfully uploaded: enter image description here


    Update:

    This is how the upload works:

    enter image description here

    I do not know how your code passed the compiling. To construct an Upload object, you need to pass a caption string and a receiver which implements Upload.Receiver interface.

    public Upload(String caption, Receiver uploadReceiver)
    

    And to implement the Upload.Receiver interface, you have to override the receiveUpload method.

    OutputStream receiveUpload(String filename, String mimeType)
    

    The receiveUpload will return an output stream, where vaadin will finally write contents to.

    That's all. Give vaadin an output stream, and it will write all the contents to the stream.

    The input file is sent from your browser and handled by vaadin. I did not find a way to manually set the input content in vaadin. Sorry.