Skip to content
This repository has been archived by the owner on Jan 19, 2022. It is now read-only.

clientconfiguration information when connecting through proxy #63

Closed
iamiddy opened this issue Mar 19, 2015 · 11 comments
Closed

clientconfiguration information when connecting through proxy #63

iamiddy opened this issue Mar 19, 2015 · 11 comments
Assignees
Labels
type: feature A new feature
Milestone

Comments

@iamiddy
Copy link

iamiddy commented Mar 19, 2015

Is there a way to Set optional proxy details on com.amazonaws.ClientConfiguration connecting through a proxy, am developing with spring-cloud-aws-version 1.0.0.RELEASE, spring-boot-version 1.2.2.RELEASE in spring-cloud-aws-autoconfigure. I want to be able to configure proxy details as follows

SO question here

@aemruli
Copy link
Contributor

aemruli commented Mar 20, 2015

Hello @iamiddy currently it is not possible to specify an own client configuration. You can create your own custom aws service instance (e.g. AmazonEC2Client) and inject the client configuration there.

We will add support to configure the ClientConfiguration soon.

@aemruli aemruli added the type: feature A new feature label Mar 20, 2015
@aemruli aemruli added this to the 1.0.1 milestone Mar 20, 2015
@aemruli aemruli self-assigned this Mar 20, 2015
@iamiddy
Copy link
Author

iamiddy commented Mar 22, 2015

Hello @aemruli I went ahead and created a custom AmazonSQSClient with ClientConfiguration thanks for the tip , and passed it to the QueueMessagingTemplate , it works great for sending Messages to SQS queues by QueueMessagingTemplate through the proxy, however the issues comes to SQS Listener @MessageMapping, how can I make it's MessageHendler to use the custom AmazonSQSClient created above?

As it is right now the below code doesn't know about my proxy and ClientConfiguration in general

  @MessageMapping(QUEUE_NAME)
    private void receiveMessage(MessageToProcess message,) {
        LOG.debug("Received SQS message {}", message);
        }

I know that I can use QueueMessagingTemplate to receive the messages, but I would rather leverage what @MessageMapping has to offer.

Thank you in advance for yet another tip

@alainsahli
Copy link
Contributor

Hi @iamiddy

If you are java config then you can achieve this by creating a SimpleMessageListenerContainerFactory bean that sets your custom client:

@Bean
public SimpleMessageListenerContainerFactory simpleMessageListenerContainerFactory() {
    SimpleMessageListenerContainerFactory factory = new SimpleMessageListenerContainerFactory();        
    factory.setAmazonSqs(yourCustomClient);

    return factory;
}

If you are using the @sendto annotation then you must also define the client of the send to messaging template:

@Bean
public QueueMessageHandlerFactory queueMessageHandlerFactory() {
    QueueMessageHandlerFactory factory = new QueueMessageHandlerFactory();
    factory.setAmazonSqs(yourCustomClient);

    return factory;
}

You can achieve the same with XML config:

<aws-messaging:annotation-driven-queue-listener amazon-sqs="yourCustomClient" send-to-message-template="messageTemplateThatUsersYourCustomClient" />

@iamiddy
Copy link
Author

iamiddy commented Mar 23, 2015

Thanks @alainsahli this worked out well

@aemruli aemruli modified the milestones: 1.0.1, 1.0.2 Apr 23, 2015
@stanislasbonifetto
Copy link

Hi, do you have some example how to configure AmazonS3Client in spring cloud when it is behind a proxy server?

@iamiddy
Copy link
Author

iamiddy commented May 12, 2015

There you go @stanislasbonifetto

 @Configuration
  @Profile("local")
  protected static class LocalAWSConfiguration {
    @Value("${proxy.host}")
    private String proxyHost;

    @Value("${proxy.port}")
    private int proxyPort;

    @Value("${proxy.user.name}")
    private String proxyUserName;

    @Value("${proxy.user.password}")
    private String proxyPassword;



    @Bean(name="amazonSQS")
    public AmazonSQSAsyncClient amazonSQSAsyncClient(AWSCredentialsProvider awsCredentialsProvider){
        return new AmazonSQSAsyncClient(awsCredentialsProvider,clientConfiguration());
    }

    @Bean(name="mazonS3Clent")
    public AmazonS3 amazonS3Client(AWSCredentialsProvider awsCredentialsProvider){
        return new AmazonS3Client(awsCredentialsProvider,clientConfiguration());
    }

    @Bean ClientConfiguration clientConfiguration(){
        ClientConfiguration clientConfiguration= new ClientConfiguration();
        clientConfiguration.setProxyHost(proxyHost);
        clientConfiguration.setProxyPort(proxyPort);
        clientConfiguration.setProxyUsername(proxyUserName);
        clientConfiguration.setProxyPassword(proxyPassword);

        return clientConfiguration;  
    }

@stanislasbonifetto
Copy link

Thank @iamiddy your code clarifies me how i need to implement.
Just to precise, i have corrected the name of the bean from "amazonS3Clent" amazonS3 to "amazonS3", so the SimpleStorageResource use it.

Below you can see my implementation:

public class AmazonS3ProxyConfiguration implements EnvironmentAware {

    private static final Logger LOG = LoggerFactory.getLogger(AmazonS3ProxyConfiguration.class);    
    private static final String PROPERTY_PREFIX = "cloud.aws.proxy";
    private static final String PROXY_HOST_PROPERTY_NAME = "host";
    private static final String PROXY_PORT_PROPERTY_NAME = "port";
    private static final String PROXY_USER_NAME_PROPERTY_NAME = "user.name";
    private static final String PROXY_PASSWORD_PROPERTY_NAME = "user.password";

    protected Environment environment;

    @Bean(name = "amazonS3")
    public AmazonS3 amazonS3Client(AWSCredentialsProvider awsCredentialsProvider) {
        AmazonS3 s3 = new AmazonS3Client(awsCredentialsProvider,clientConfiguration());
        return s3;
    }

    @Bean
    ClientConfiguration clientConfiguration() {

        ClientConfiguration clientConfiguration = new ClientConfiguration();
        clientConfiguration.setProtocol(Protocol.HTTPS);

        if (containsProperty(PROXY_HOST_PROPERTY_NAME)) {
            clientConfiguration.setProxyHost(getProperty(PROXY_HOST_PROPERTY_NAME));
        }
        if (containsProperty(PROXY_PORT_PROPERTY_NAME)) {
            clientConfiguration.setProxyPort(Integer.parseInt(getProperty(PROXY_PORT_PROPERTY_NAME)));
        }
        if (containsProperty(PROXY_USER_NAME_PROPERTY_NAME)) {
            clientConfiguration.setProxyUsername(getProperty(PROXY_USER_NAME_PROPERTY_NAME));
        }
        if (containsProperty(PROXY_PASSWORD_PROPERTY_NAME)) {
            clientConfiguration.setProxyPassword(getProperty(PROXY_PASSWORD_PROPERTY_NAME));
        }

        return clientConfiguration;
    }


    private boolean containsProperty(String name) {
        return this.environment.containsProperty(PROPERTY_PREFIX + "." + name);
    }

    private String getProperty(String name) {
        return this.environment.getProperty(PROPERTY_PREFIX + "." + name);
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}

@aemruli aemruli modified the milestones: 1.0.2, 1.1 Jun 25, 2015
@ashvolunteering
Copy link

Hi,

I tried the JavaConfig method for S3 and it worked fine. I can't get it to work for SQS. I keep getting connection time out. I tried with different return types AmazonSQSAsyncClient, AmazonSQSAsync, AmazonSQS. The program works if I use my personal wireless instead of the company wireless so that tells me that the clientconfiguration is not getting picked up and used.

Any suggestions?

Also, there was some mention about adding the ability to configure the client in the sping cloud aws framework itself but can't fond anything on the plans for that.

Thanks,

Ashvin

@dsyer dsyer modified the milestones: 1.1.0.RC1, Backlog May 11, 2016
@eballetbaz
Copy link

Adding this feature is quite simple: extends class AmazonWebserviceClientFactoryBean and add a setter to inject a ClientConfiguration, then in method createInstance simply add lines :
if (this.clientConfiguration != null) {
builder.withClientConfiguration(this.clientConfiguration);
}

@nberserk
Copy link

@eballetbaz do you have working example or reference ?

@eballetbaz
Copy link

eballetbaz commented Jan 31, 2018

/**
 * Copy of {@link AmazonWebserviceClientFactoryBean} to add support for {@link ClientConfiguration}
 */
public class ConfigurableAmazonWebserviceClientFactoryBean<T extends AmazonWebServiceClient> extends AbstractFactoryBean<T> {

    private final ClientConfiguration _clientConfiguration;
   
    private final Class<? extends AmazonWebServiceClient> clientClass;
    private final AWSCredentialsProvider credentialsProvider;
    private RegionProvider regionProvider;
    private Region customRegion;
    private ExecutorService executor;

    public ConfigurableAmazonWebserviceClientFactoryBean(
        Class<T> clientClass,
        ClientConfiguration clientConfiguration, 
        AWSCredentialsProvider credentialsProvider) {
        
        this.clientClass = clientClass;
        this.credentialsProvider = credentialsProvider;
        _clientConfiguration = clientConfiguration;
    }

    public ConfigurableAmazonWebserviceClientFactoryBean(
        Class<T> clientClass,
        ClientConfiguration clientConfiguration, 
        AWSCredentialsProvider credentialsProvider, 
        RegionProvider regionProvider) {
        
        this(clientClass, clientConfiguration, credentialsProvider);
        setRegionProvider(regionProvider);
    }

    @Override
    public Class<?> getObjectType() {
        return this.clientClass;
    }

    @SuppressWarnings("unchecked")
    @Override
    protected T createInstance() throws Exception {

        String builderName = this.clientClass.getName() + "Builder";
        Class<?> className = ClassUtils.resolveClassName(builderName, ClassUtils.getDefaultClassLoader());

        Method method = ClassUtils.getStaticMethod(className, "standard");
        Assert.notNull(method, "Could not find standard() method in class:'" + className.getName() + "'");

        AwsClientBuilder<?, T> builder = (AwsClientBuilder<?, T>) ReflectionUtils.invokeMethod(method, null);

        if (this.executor != null) {
            AwsAsyncClientBuilder<?, T> asyncBuilder = (AwsAsyncClientBuilder<?, T>) builder;
            asyncBuilder.withExecutorFactory(() -> executor);
        }

        if (this.credentialsProvider != null) {
            builder.withCredentials(this.credentialsProvider);
        }

        if (this.customRegion != null) {
            builder.withRegion(this.customRegion.getName());
        } else if (this.regionProvider != null) {
            builder.withRegion(this.regionProvider.getRegion().getName());
        } else {
            builder.withRegion(Regions.DEFAULT_REGION);
        }
        
        if (_clientConfiguration != null) {
            builder.withClientConfiguration(_clientConfiguration);
        }
        return builder.build();
    }

    public void setRegionProvider(RegionProvider regionProvider) {
        this.regionProvider = regionProvider;
    }

    public void setCustomRegion(String customRegionName) {
        this.customRegion = RegionUtils.getRegion(customRegionName);
    }

    public void setExecutor(ExecutorService executor) {
        this.executor = executor;
    }

    @Override
    protected void destroyInstance(T instance) throws Exception {
        instance.shutdown();
    }
}

maciejwalkowiak pushed a commit to maciejwalkowiak/spring-cloud-aws that referenced this issue Oct 15, 2020
…verter-for-messaging-templates

Feature/composite converter for messaging templates
juho9000 pushed a commit to juho9000/spring-cloud-aws that referenced this issue Apr 29, 2021
…ure/composite-converter-for-messaging-templates

Feature/composite converter for messaging templates
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
type: feature A new feature
Development

No branches or pull requests

8 participants