I'm using the AWS Java SDK v1 and I'm trying to create an AmazonS3 instance using the builder. I'm following the guide in the AWS documentation here and passing explicit credentials using a BasicAWSCredentials object. When the builder builds, I get a null client back to s3Client
which is where I'm storing the instance, and I'm not sure why. There are no errors thrown or caught by the try-catch blocks. Here is how I am making the connection:
BasicAWSCredentials awsCreds = null;
try {
awsCreds = new BasicAWSCredentials(settings.getAccessKey(), settings.getSecretKey());
} catch (Exception e) {
e.printStackTrace();
throw new IOException(e.getMessage());
}
try {
AmazonS3 s3Client = AmazonS3Client.builder()
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.withRegion(Regions.US_EAST_1)
.build();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(s3Client);
I have stepped through it with the Eclipse debugger and it looks like the build()
call is actually returning a valid AmazonS3Client instance, but then before this reference is returned back to the s3Client
variable, there's a step in which checkPackageAccess()
is called, and this return value is what is being returned back for some reason. On further inspection I found that checkPackageAccess()
is a method in the java.lang.ClassLoader that's being called by the JVM, and it has a void return type. In my application, it looks like there's no default SecurityManager set, so there's no other function called inside the ClassLoader's checkPackageAccess()
method.
I'm a bit confused by this behavior. My JRE is 1.8. So far as I understand, the ClassLoader is always called when looking for a class definition, but why would it be called after a class has already been instantiated, and why is the original return value of the build()
function not coming back to the caller context? In this case, the debugger shows a valid AmazonS3Client object exists and is returned by the call to build()
even before the checkPackageAccess call.
I've made an AmazonRedshift instance with almost identical code in the same project previously, and that worked without a hitch, so I'm quite positive the problem is with the AmazonS3 class or the builder, but I'm not sure where and I'm not seeing any errors or strange prints.
Code used for making a similar connection to Amazon Redshift:
BasicAWSCredentials awsCreds = null;
try {
awsCreds = new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY);
} catch (Exception e) {
e.printStackTrace();
throw new IOException(e.getMessage());
}
try {
client = AmazonRedshiftClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.withRegion(Regions.US_EAST_1)
.build();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(client);
Has anyone debugged this kind of issue before? What can I do to resolve this and get back a valid instance?
The problem ended up being far more fundamental. I feel almost embarrassed to write this. I had to get a second pair of eyes on my code to find it, but I was redeclaring the s3Client within the try block.
private AmazonS3 s3Client = null;
...
BasicAWSCredentials awsCreds = null;
try {
awsCreds = new BasicAWSCredentials(settings.getAccessKey(), settings.getSecretKey());
} catch (Exception e) {
e.printStackTrace();
throw new IOException(e.getMessage());
}
try {
AmazonS3 s3Client = AmazonS3Client.builder()
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.withRegion(Regions.US_EAST_1)
.build();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(s3Client);
By the time it reached the code that actually used the AmazonS3 object, the local variable holding a reference to it had already passed out of scope. Can't believe I didn't catch this.