2

How/where can I compute md5 digest for a file I need to transfer to a samba location in spring-integration in order to validate it against the digest I receive at the beginning of the flow. I get the file from a rest service and I have to make sure file is safely landing to samba location. The middle flow looks like this: (the digest to be compared against is stored somewhere in the messages)

GenericHandler smbUploader;
HttpRequestExecutingMessageHandler httpDownloader;
from(inbound())   //here I receive a notification with url where to download file + a checksum to be validated against
...
.handle(httpDownloader)     //here I get file effectively
.handle(smbUploader)  //here I upload the file to samba
...

and httpDownloader is defined like this:

public HttpRequestExecutingMessageHandler httpDownloader(){
  HttpRequestExecutingMessageHandler  h = new HttpRequestExecutingMessageHandler ("payload.url");
  h.setExpectedResponseType(String.class); 
  h.setHttpMethod(GET); 
  return h; 
}

and smbUploader is defined like this:

public GenericHandler smbUploader (MessageHandler smbMessageHandler){
  return new GenericHandler<Message>(){
  @Override
  public Message handle(Message m, MessageHeaders h){
    smbMessageHandler.handleMessage(m);
    return m;
  }
}

and smbMessageHandler is defined like this:

public MessageHandler smbMessageHandler (SmbRemoteFileTemplate template, FileNameGenerator g){
  SmbMessageHandler h = new smbMessageHandler (template, REPLACE);
  h.setAutoCreateDirectory(true);    
  h.setRemoteDirectoryExpression(getExpression("headers['msg'].smbFolder"));
  h.setFileNameGenerator(g);
  return h;
}

the inbound (starting the flow) is defined like this:

public HttpRequestHandlerEndpointSpec inbound(){
  return Http.inboundChannelAdapter ("/notification")
    .requestMapping(m->m.methods(POST))
    .requestPayloadType(String.class)
    .validator(notificationValidator);
}
MS13
  • 327
  • 5
  • 16
  • Give us, please, more info what that checksum you'd like to get from? – Artem Bilan Mar 15 '22 at 13:26
  • The checksum is received in the notification at the begining of the flow from external service (inbound) and should be compared with the checksum of the file downloaded by httpDownloader in order to filter out problems – MS13 Mar 16 '22 at 13:40

1 Answers1

0

First of all you should store a digest in the message headers in the beginning of the flow.

Then you need to write a service method to calculate a checksum of the file you got downloaded. And insert a new handle() in between:

.handle(httpDownloader)     //here I get file effectively
.handle(smbUploader)  //here I upload the file to samba

to call your service method. The input for that method must be a whole Message, so you got access to the downloaded file in the payload and digest in the headers. The result of this method could be just your file to proceed into an SMB handler for uploading.

How to calculate a checksum you can find in this SO thread: Getting a File's MD5 Checksum in Java

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • Forgot to tell you that files downloaded are quite large (4-7G). Will this work? – MS13 Mar 16 '22 at 20:45
  • Look here then: https://stackoverflow.com/questions/9321912/very-slow-to-generate-md5-for-large-file-using-java – Artem Bilan Mar 16 '22 at 21:08
  • Thanks but more important aspect is how will the spring integration will perform? how will streaming be used? – MS13 Mar 17 '22 at 00:03
  • I'm not in your question. The `MD5.asHex(MD5.getHash(new File(filename)))` doesn't require a stream from you, just a file path. I believe you should be able already to download that file to the local dir in the `httpDownloader`. So, the local file path is returned from this service to be able to calculate checksum and go ahead with SMB upload. – Artem Bilan Mar 17 '22 at 13:32
  • 1
    If you think about calculating checksum on the fly, when you download the file, the you need a custom `HttpMessageConverter` which is going to read an `InputStream` from the `ClientHttpResponse.getBody()`, calculate the hash during the write and store the local file path and checksum in the composite object to return from the `RestTemplate.execute()` . You cannot modify HTTP headers from response. Therefore some composite object for both data you need. – Artem Bilan Mar 17 '22 at 13:33