3

In my CF project, I'm working with the AWS Java 2.0 SDK and I'm trying to implement an async multi part upload, but I'm running into some trouble getting things set up, specifically in creating a BiConsumer Interface.

Docs: createMultipartUpload(CreateMultipartUploadRequest createMultipartUploadRequest)

To start this process I have to call a3AsyncInterface.createMultipartUpload() and so I create a CreateMultipartUploadRequest object and pass that object into my call:

oCreateMultipartUploadRequest = createObject( 'java', 'software.amazon.awssdk.services.s3.model.CreateMultipartUploadRequest' ).builder()
                                .bucket( ARGUMENTS.bucket )
                                .key( ARGUMENTS.key )
                                .contentType( ARGUMENTS.fileMimeType )
                                .build();

oCreateMultipartUploadResponse = s3AsyncInterface.createMultipartUpload( oCreateMultipartUploadRequest );

So this all works great so far. My call returns a response object of type CompletableFuture<CreateMultipartUploadResponse>, but here's where it starts to fall apart.

From the CompletableFuture, I want to call it's .whenComplete() method but I can't figure out how to do this successfully.

The .whenComplete() method takes an object of type BiConsumer<? super T,? super Throwable> (docs) and I can't figure out how to create this object. BiConsumer is a Java Interface, so it doesn't have a constructor. I can create an object no problem, but that doesn't seem to cut it.

oBiConsumer = createObject( 'java', 'java.util.function.BiConsumer' );

I can't call the .accept( t, u ) method on this BiConsumer object because I haven't set it up correctly I think. It's .andThen() method takes another BiConsumer object so I still have to figure that out first it seems.

So what I think I want to be doing in Coldfusion is something like this (example in Java):

BiConsumer< List<Integer>, List<Integer> > equals = ( list1, list2 ) ->
{
    if ( list1.size() != list2.size() ) {
        System.out.println( 'False' );
    } else {
        for ( int i = 0; i < list1.size(); i++ ) {
            if ( list1.get( i ) != list2.get( i ) ) {
                System.out.println( 'False' );
                return;
            }
        }
        System.out.println( 'True' );
    }
};
equals.accept( lista, listb );

Not sure if I need to even call the .accept() method right way, or kinda call it when I pass my arguments into .whenComplete(). I may be going about this specific action all wrong, but that's fine, I can figure that out then when I get there. I still want to figure out how to set up the BiConsumer object properly, this seems to be a popular pattern in Java and I want to be able to work with it.

What I would love to be able to do is something like this:

oBiConsumer = createObject( 'java', 'java.util.function.BiConsumer<T, U>' );

But that doesn't seem to be supported, and I'm not sure if there's a different syntax to accomplish the same thing.

I get that I can go down the road of creating a dynamic proxy and a custom .jar to create/build this functionality, but is this the only way forward? I would greatly prefer to not have to do that if possible; stinks to maintain.

Any suggestions would be appreciated.

The Red Duke
  • 163
  • 10
  • `so it doesn't have a constructor.` Yeah interfaces do nothing because they don't have an implementation or "code behind them". You have to provide that by creating a class that *implements* the interface. Either write a custom java class OR use CF code and implement the interface using a cfcomponent and CFCDynamicProxy. – SOS Jan 16 '20 at 16:46
  • Yep, I follow on the Interface. Question is, is using CFC DynamicProxy my only path forward on this? I was hoping that there would be some other slick way to get this accomplished without going down that road. – The Red Duke Jan 16 '20 at 19:37
  • 1
    AFAIK, the only options are to write it in java or write it in CF and use CFCDynamicProxy. What's wrong with using a proxy? :-) I'm more familiar with Adobe CF, but aside from an extra function call or two, the backing code is pure CF and the whole "typing" thing is less of an issue than in java (since CF is loosely typed). Not quite as sleek as the inline java example, but certainly a lot simpler than creating a custom jar. – SOS Jan 16 '20 at 20:29

0 Answers0