Manage RDS access with AWS Secrets Manager - java

I am currently working with Eclipse and the AWS Toolkit for Eclipse. My project already works and it is doing its job, which is to connect to an RDS instance and return JSON objects to API Gateway calls.
I just got a new requirement, we are to use the service SecretsManager to authomatically rotate RDS configuration such as Users, passwords and so on.
The problem is when I try to import classes such as GetSecretValueResponse, I get a The import com.amazonaws.services.secretsmanager cannot be resolved. When I explore the documentation and the SDK, there exists a GetSecretValueRequest but not a GetSecretValueResponse, so I am not being able to make sense on what should I do, nor I have found anything similar to an example I can study.
The following code is what I am trying to implement and is given by Amazon itself (in the Secrets Manager page there is a button you can click to see how it would go with Java, in this case), and it is presented without any modification yet because as I said I do not know how to import several classes:
// Use this code snippet in your app.
public static void getSecret() {
String secretName = "secretName";
String endpoint = "secretEndpoint";
String region = "region";
AwsClientBuilder.EndpointConfiguration config = new AwsClientBuilder.EndpointConfiguration(endpoint, region);
AWSSecretsManagerClientBuilder clientBuilder = AWSSecretsManagerClientBuilder.standard();
clientBuilder.setEndpointConfiguration(config);
AWSSecretsManager client = clientBuilder.build();
String secret;
ByteBuffer binarySecretData;
GetSecretValueRequest getSecretValueRequest = GetSecretValueRequest.builder()
.withSecretId(secretName)
.build();
GetSecretValueResponse getSecretValueResponse = null;
try {
getSecretValueResponse = client.getSecretValue(getSecretValueRequest);
} catch(ResourceNotFoundException e) {
System.out.println("The requested secret " + secretName + " was not found");
} catch (InvalidRequestException e) {
System.out.println("The request was invalid due to: " + e.getMessage());
} catch (InvalidParameterException e) {
System.out.println("The request had invalid params: " + e.getMessage());
}
if(getSecretValueResponse == null) {
return;
}
// Decrypted secret using the associated KMS CMK
// Depending on whether the secret was a string or binary, one of these fields will be populated
if(getSecretValueResponse.getSecretString() != null) {
secret = getSecretValueResponse.getSecretString();
}
else {
binarySecretData = getSecretValueResponse.getSecretBinary();
}
// Your code goes here.
}

I had the same problem, the code that is present on AWS page doesn't work out of the box. The class you are looking for is GetSecretValueResult
Here are the latest java docs
https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/secretsmanager/model/GetSecretValueResult.html
Here is a piece that shall work:
public void printRdsSecret() throws IOException {
String secretName = "mySecretName";
System.out.println("Requesting secret...");
AWSSecretsManager client = AWSSecretsManagerClientBuilder.standard().build();
GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest().withSecretId(secretName);
GetSecretValueResult getSecretValueResult = client.getSecretValue(getSecretValueRequest);
System.out.println("secret retrieved ");
final String secretBinaryString = getSecretValueResult.getSecretString();
final ObjectMapper objectMapper = new ObjectMapper();
final HashMap<String, String> secretMap = objectMapper.readValue(secretBinaryString, HashMap.class);
String url = String.format("jdbc:postgresql://%s:%s/dbName", secretMap.get("host"), secretMap.get("port"));
System.out.println("Secret url = "+url);
System.out.println("Secret username = "+secretMap.get("username"));
System.out.println("Secret password = "+secretMap.get("password"));
}
This was tested with aws-java-sdk-secretsmanager of version 1.11.337

I think the main problem was in lack of dependencies to AWS SDK v2.
Adding a code snippet here that utilizes AWS SDK v2. Just in case anybody is looking for this.
package com.may.util;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
import software.amazon.awssdk.services.secretsmanager.model.DecryptionFailureException;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse;
import software.amazon.awssdk.services.secretsmanager.model.InternalServiceErrorException;
import software.amazon.awssdk.services.secretsmanager.model.InvalidParameterException;
import software.amazon.awssdk.services.secretsmanager.model.InvalidRequestException;
import software.amazon.awssdk.services.secretsmanager.model.ResourceNotFoundException;
public class SecretsManagerUtil {
public static String obtainSecret() {
String secretName = "db_secret_name";
String region = "us-east-1";
SecretsManagerClient client = SecretsManagerClient.builder().region(Region.of(region)).build();
GetSecretValueResponse response = null;
try {
response = client.getSecretValue(GetSecretValueRequest.builder().secretId(secretName).build());
} catch (DecryptionFailureException e) {
// Secrets Manager can't decrypt the protected secret text using the provided KMS key.
// Deal with the exception here, and/or rethrow at your discretion.
throw e;
} catch (InternalServiceErrorException e) {
// An error occurred on the server side.
// Deal with the exception here, and/or rethrow at your discretion.
throw e;
} catch (InvalidParameterException e) {
// You provided an invalid value for a parameter.
// Deal with the exception here, and/or rethrow at your discretion.
throw e;
} catch (InvalidRequestException e) {
// You provided a parameter value that is not valid for the current state of the resource.
// Deal with the exception here, and/or rethrow at your discretion.
throw e;
} catch (ResourceNotFoundException e) {
// We can't find the resource that you asked for.
// Deal with the exception here, and/or rethrow at your discretion.
throw e;
}
return response.secretString();
}
}
Deserialize and print secret:
public class SecretPrinter {
private static final Logger logger = LoggerFactory.getLogger(SecretPrinter.class);
public void printSecret() {
String json = SecretsManagerUtil.obtainSecret(); // secret in json format
RdsSecret secret;
try {
secret = new ObjectMapper().disable(FAIL_ON_UNKNOWN_PROPERTIES).readValue(json, RdsSecret.class);
} catch (IOException e) {
logger.error("Couldn't parse secret obtained from AWS Secrets Manager!");
throw new RuntimeException(e);
}
System.out.println("username: " + secret.getUsername());
System.out.println("password: " + secret.getPassword());
}
static class RdsSecret {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
}
Maven:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.6.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>secretsmanager</artifactId>
</dependency>
Gradle:
implementation platform('software.amazon.awssdk:bom:2.6.3')
implementation 'software.amazon.awssdk:secretsmanager'

aws-secretsmanager-jdbc can be used to access AWS RDS via AWS secrete manager.
https://github.com/aws/aws-secretsmanager-jdbc
Below is the content of my application.properties
spring.datasource.url=jdbc-secretsmanager:mysql://dev-xxxx-database.cluster-xxxxxxxxx.ap-southeast-1.rds.amazonaws.com:3306/dev_xxxxxx
spring.datasource.username=/secret/application
spring.datasource.driver-class-name=com.amazonaws.secretsmanager.sql.AWSSecretsManagerMySQLDriver
spring.jpa.database-platform = org.hibernate.dialect.MySQL5Dialect
Below is the secret in AWS secret manager.
By using this method, you don't need to obtain username and password manually and create data sources.

just add the lib to your pom:
https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-secretsmanager

I recommend using aws secret manger jdbc wrapper to access the RDS (https://github.com/aws/aws-secretsmanager-jdbc). You don't need to deal with fetching the secret, decode and move around with password in text before passing to RDS client.
Just pass in secret id to RDS client and the jdbc wrapper will handle the rest.

I have faced the same issue. just delete the scope line i.e "test" from the dependency. It'll work

You're missing "aws-java-sdk-secretsmanager" dependency, you have to add this to your pom.xml and then import on your java class.
From Maven:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-secretsmanager</artifactId>
<version>1.11.355 </version>
</dependency>
AWS Reference
If you are not using maven, you have add AWS SDK to your existing project.

Related

Are the Azure Workload Identity (Client Assertion) tokens compatible with the msal4j token cache?

I'm trying to use the Azure Workload Identity MSAL Java Sample, and I'm trying to figure out if the built-in token cache that comes with MSAL4J is actually usable with Azure Workload Identity (Client Assertions), as my understanding is that every time you request a new token, you need to read the AZURE_FEDERATED_TOKEN_FILE again (See // 1). I've looked through the MSAL4J code and to me it looks like you'd need to throw away the ConfidentialClientApplication (see // 2) and create a brand new one to load in a new federated token file, because the clientAssertion ends up baked into the client. So then I'd need to do my own checks to figure out if I need if I need to recreate the client, basically defeating the purpose of the built-in client.
Are my assumptions correct? Or is there some way to hook into the token refresh process and reload the clientAssertion?
Maybe MSAL4J needs integrated token cache support for Azure Workload Identity that handles the reloading of the client assertion on renewal?
Here is the sample code included for context.
public class CustomTokenCredential implements TokenCredential {
public Mono<AccessToken> getToken(TokenRequestContext request) {
Map<String, String> env = System.getenv();
String clientAssertion;
try {
clientAssertion = new String(Files.readAllBytes(Paths.get(env.get("AZURE_FEDERATED_TOKEN_FILE"))),
StandardCharsets.UTF_8); // 1
} catch (IOException e) {
throw new RuntimeException(e);
}
IClientCredential credential = ClientCredentialFactory.createFromClientAssertion(clientAssertion);
String authority = env.get("AZURE_AUTHORITY_HOST") + env.get("AZURE_TENANT_ID");
try {
ConfidentialClientApplication app = ConfidentialClientApplication
.builder(env.get("AZURE_CLIENT_ID"), credential).authority(authority).build(); // 2
Set<String> scopes = new HashSet<>();
for (String scope : request.getScopes())
scopes.add(scope);
ClientCredentialParameters parameters = ClientCredentialParameters.builder(scopes).build();
IAuthenticationResult result = app.acquireToken(parameters).join();
return Mono.just(
new AccessToken(result.accessToken(), result.expiresOnDate().toInstant().atOffset(ZoneOffset.UTC)));
} catch (Exception e) {
System.out.printf("Error creating client application: %s", e.getMessage());
System.exit(1);
}
return Mono.empty();
}
}

Login success on FTP over explicit SSL/TLS but unable to browse the files

I have been asked to make the secure FTP Server connection. FTP over explicit TLS/SSL. In order to achieve this, I have added a below line in the existing implementation. This is my FTPClient lib - it.sauronsoftware.ftp4j - version 1.6.1
ftpClient.setSecurity(FTPClient.SECURITY_FTPES);
// Existing code
ftpClient.setConnector(new HTTPTunnelConnector(proxyHost, proxyPort));
ftpClient.connect(getFtpHost(), getFtpPort());
ftpClient.login(getUsername(), getPassword());
ftpClient.setAutoNoopTimeout(30000);
When I deployed the code on JBOSS 5.1, I am getting successful connection, but I am unable to list the files in the root directory. we only have permission to access the root directory.
On the other hand, I have written a standalone client (java main program) - through which I can print the files present at FTP location, by this way I have ensured the secure connection and the files availability at FTP location. Here, I have used the
My problem is, when I make a secure connection through the deployed application I am getting the unable to locate any files at remote location. ie: FTPFiles.length is 0
Any help would be much appreciated, thank you!
Adding few more logs and info,
Normal Flow without FTPES security parameter added (current Implementation)
printing ftpClient.serverStatus()
msg: Status of 'FTP Service'
msg: Connected from ec2-xyz
msg: Logged in as <user>
msg: TYPE: BINARY, STRUcture: File, Mode: Stream
msg: Total bytes transferred for session: 10511
msg: No data connection
msg: End of status
printing ftpClient.serverStatus() With FTPES added
msg: Status of 'FTP Service'
msg: Connected from ec2-xyz
msg: Logged in as <user>
msg: TYPE: ASCII, STRUcture: File, Mode: Stream
msg: No data connection
msg: End of status
Few questions which I need to know answers (may be that give a lead to fix):
Here, TYPE: BINARY is changed to ASCII and can someone tell how to modify back to BINARY? Note tehre is no explicit setting made, got changed post FTPES set
Is this issue related to proxy / port. if so - I wont be able to provide those information.
As of now, I am testing with same proxy used which is used in the application.
Is there any certificates to be imported to get files viewed / downloaded.
Found this on net which is exactly same as my issue, http://www.proftpd.org/docs/howto/TLS.html ( search for -"I can login using FTPS, but I cannot see any directories. Why not?") but I need to explain my third party to make the required change... what should I tell?
stand alone client code
import it.sauronsoftware.ftp4j.*;
import javax.net.ssl.*;
import java.io.File;
import java.security.*;
import java.util.List;
public class FTPWithSSL {
private static FTPClient ftpClient;
private static FTPConfig ftpConfig;
private DailyFTPConfig config;
public static void main(String args[]) throws Exception {
ftpConfig = new FTPConfig("username", "password", "FTPServer.net", 21, setupConnector());
FTPDownloader ftpDownloader = new FTPDownloader(ftpConfig, new FTPDownloadController() {
#Override
public List<FTPFile> download(FTPClient ftpClient) throws Exception {
downloadFile(ftpClient);
System.out.println("download success");
return null;
}
});
try {
openConnection();
List<FTPFile> ftpFileList = ftpDownloader.download();
closeConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void openConnection() throws Exception {
System.out.println("OpenConnection method");
if (ftpClient == null) {
ftpClient = new FTPClient();
// Even if the below line is commented, the code works fine
ftpClient.setSSLSocketFactory(getSSLSocketFactory());
System.out.println("setting FTPES here");
ftpClient.setSecurity(FTPClient.SECURITY_FTPES);
ftpClient.setConnector(ftpConfig.getConnector());
ftpClient.connect(ftpConfig.getFtpHost(), ftpConfig.getFtpPort());
ftpClient.login(ftpConfig.getUsername(), ftpConfig.getPassword());
ftpClient.setAutoNoopTimeout(30000);
System.out.println("ftpClient.isConnected() " + ftpClient.isConnected());
}
}
private static SSLSocketFactory getSSLSocketFactory() throws Exception {
TrustManager[] trustManager = new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManager, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
return sslSocketFactory;
}
private static void closeConnection() throws Exception {
System.out.println("ftpClient.serverStatus() -- ");
for (String serverStatus : ftpClient.serverStatus()) {
System.out.println(" msg: " + serverStatus);
}
if (ftpClient != null && ftpClient.isConnected()) {
ftpClient.disconnect(false);
}
}
private static void downloadFile(FTPClient ftpClient) throws Exception {
System.out.println("ftpsClient.currentDirectory() " + ftpClient.currentDirectory());
FTPFile[] ftpFile = ftpClient.list();
System.out.println("Name " + ftpFile[0].getName());
System.out.println("Link " + ftpFile[0].getLink());
System.out.println("Modified Date " + ftpFile[0].getModifiedDate());
String[] listnames = ftpClient.listNames();
System.out.println("ftpsClient.listNames() " +listnames);
System.out.println("ftpsClient.currentDirectory() " + ftpClient.list());
File file = new File( "C:\\opt\\copycat\\a1234.zip");
System.out.println("Downloading File: [" + file.getName() + "] has started.");
ftpClient.download("a1234.zip", file);
System.out.println("Downloading File: has Completed");
}
private static FTPConnector setupConnector() {
FTPConnector connector = new DirectConnector();
String proxyHost = "amazonaws.com";
if (proxyHost != null) {
System.out.println("proxy host NOT NULL");
int proxyPort = Integer.parseInt("123");
connector = new HTTPTunnelConnector(proxyHost, proxyPort);
}
return connector;
}
}
Finally, I am able to make the secure connection and able to download the latest files from FTP server using FTPES (FTP over explicit TLS/SSL).
I have made only 2 line code changes (below), in the actual implementation. earlier it was having the list() method to get the files from FTP server, and its return type is FTPFile[]
This is the code changes which I made, and other line of codes are modified / removed.
ftpClient.setSecurity(FTPClient.SECURITY_FTPES);
// get the FTP connection
String[] fileNames = ftpClient.listNames();
// Exisitng implementation
FTPFile[] ftpFiles = ftpClient.list("*.zip");
// after that there is an implementation for getting the latest files using the Comparator<FTPFile>
There was an issue with the LIST command's output, ie: LIST *.zip is not giving the correct output (I guess)

Google Maps API (Directions) throws 403 error in Payara, not in WebLogic

I've been given the task to move our application from WebLogic 12.1.3 to Payara 4.1 and have run into an issue that I feel I'm more or less at the end of the line of troubleshooting.
We have an EJB (a Stateless bean) that has two methods, one that makes a call to the Google Maps Directions API and one that makes a call to the Google Maps Geocoding API, both using the same credentials and Googles client libraries for Java. Both methods work perfectly running on WebLogic, but after switching to Payara the one using the Directions API gives me an error. Here's the relevant part of the stacktrace:
java.io.IOException: Server Error: 403 Forbidden
at com.google.maps.internal.OkHttpPendingResult.parseResponse(OkHttpPendingResult.java:258)
at com.google.maps.internal.OkHttpPendingResult.await(OkHttpPendingResult.java:167)
at com.google.maps.PendingResultBase.await(PendingResultBase.java:56)
at com.somecompany.integration.GoogleDirectionsIntegration.getDirections(GoogleDirectionsIntegration.java:XXX)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
So the geocoding-method still works on both platforms, but when attempting the call to the Directions API I get a 403 back from Google indicating that my credentials are messed up, but the very same credentials work for the geocoding call. The code hasn't been changed in any way switching from one platform to the other.
What's even more confusing is that if I grab the actual URL of the call to Google from the logs and try it in my browser, i.e. paste "https://maps.googleapis.com/maps/api/directions/json?client=gme-company&mode=driving&arrival_time=1435825037&o
rigin=Somewhere&destination=Somewhere+else&alternat
ives=false&signature=nfre3XYZ2kmuDX8Qibce87ZFKQQ=" into Chrome, it works. I get a proper answer from Google. (btw, those aren't the actual credentials or origin and destination I'm using, they've been "anonymized" :-)). I've also checked that this URL (which is built by the client library) is the same running on both platforms as well as used the URL Signing Debugger on Google's developer pages, but to no avail. There should be nothing wrong with my credentials.
I'm really at the end of the line here, having spent days troubleshooting and searching online without finding a solution.
Not that it matters that much but I didn't write this code myself, and the person who did of course doesn't work here anymore :-P
Anyway, here's the code (somewhat anonymized):
#Stateless
public class GoogleDirectionsIntegration {
private static final Logger LOGGER = Logger.getLogger(GoogleDirectionsIntegration.class.getName());
private GeoApiContext context = null;
/**
* Initializer
*/
#PostConstruct
public void init() {
LOGGER.log(Level.INFO, "initiating {0}", this.getClass().getSimpleName());
this.context = new GeoApiContext().setEnterpriseCredentials("gme-company", "companyGoogleCryptographicSecret");
this.context.setReadTimeout(1, TimeUnit.SECONDS)
.setRetryTimeout(1, TimeUnit.SECONDS)
.setConnectTimeout(1, TimeUnit.SECONDS)
.setWriteTimeout(1, TimeUnit.SECONDS);
OkHttpRequestHandler okHttpRequestHandler = null;
OkHttpClient okHttpClient = null;
try {
Field requestField = this.context.getClass().getDeclaredField("requestHandler");
requestField.setAccessible(true);
okHttpRequestHandler = (OkHttpRequestHandler) requestField.get(this.context);
Field f = okHttpRequestHandler.getClass().getDeclaredField("client");
f.setAccessible(true);
okHttpClient = (OkHttpClient) f.get(okHttpRequestHandler);
} catch (NoSuchFieldException | SecurityException | IllegalAccessException | IllegalArgumentException e) {
throw new IllegalStateException("Failed to create SSL context", e);
}
SSLContext sslCtx = this.getSslContext();
if (sslCtx != null && okHttpClient != null) {
SSLSocketFactory sslSocketFactory = sslCtx.getSocketFactory();
okHttpClient.setSslSocketFactory(sslSocketFactory);
}
}
private SSLContext getSslContext() {
TrustManager[] tm = new TrustManager[] {
new CustomTrustManager()
};
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, tm, new SecureRandom());
} catch (NoSuchAlgorithmException | KeyManagementException ex) {
throw new IllegalStateException("Failed to create SSL context", ex);
}
return sslContext;
}
public DirectionsRoute getDirections(final String origin, final String destination, final DistanceUnit distanceUnit,
#Nullable TransportMode mode, #NotNull Instant arrivalTime) throws NotFoundException {
TransportMode actualMode = mode == null ? TransportMode.CAR : mode;
DirectionsRoute[] directionsRoutes;
DirectionsApiRequest directionsApiRequest = DirectionsApi.getDirections(this.context, origin, destination);
directionsApiRequest.arrivalTime(new Instant(arrivalTime));
directionsApiRequest.alternatives(false);
directionsApiRequest.mode(this.toTravelMode(actualMode));
try {
DirectionsResult res = directionsApiRequest.await(); // THIS IS WHERE IT BREAKS!
directionsRoutes = res.routes;
} catch (Exception e) {
LOGGER.log(Level.WARNING, e.getMessage(), e);
throw new NotFoundException(e.getMessage());
}
if (directionsRoutes.length != 1) {
throw new NotFoundException("Failed to fetch valid directions");
}
return directionsRoutes[0];
}
public void getAddress(LatLng startLocation, Location location, boolean cacheOverride) throws Exception {
com.google.maps.model.LatLng gLatLng = new com.google.maps.model.LatLng(startLocation.getLat(), startLocation.getLng());
GeocodingApiRequest geocodingApiRequest = GeocodingApi.reverseGeocode(this.context, gLatLng);
GeocodingResult[] geocodingResults;
geocodingResults = geocodingApiRequest.await();
if (0 < geocodingResults.length) {
//.. Code that does stuff with the result..
} else {
LOGGER.log(Level.WARNING, "Received empty results from Google reverse geocode for [{0}].", startLocation);
}
}
}
So I solved it. The problem wasn't in the code but in the dependencies, or rather in a dependency to one of the dependencies - OkHttp. I simply changed the version and it works now.

VMWare vRealize Operations REST API java password prompt for basic auth

With the code I'm using VMWare created an object factory to use with their Rest API. One of them is a clientconfig class which allows me to connect to the Rest API Service.
I'm trying to prompt the user to input the password versus storing it in my java client. I suspect I have to remove the basicauth object and replace it, however I'm hoping there might be an easier way.
Here is my code:
public static void main(String[] args) {
try {
Client client = ClientConfig
.builder()
.serverUrl("https://vrops-ip-address/suite-api")
.basicAuth("admin", "password")
.verify("false")
.useJson()
.build()
.newClient();
// retrieve list of all adapter instances
AdapterInstancesInfoDto adapterInstances = client.adapterInstancesClient().list();
// get actual set of adapters
Set<AdapterInstanceInfoDto> adapters = adapterInstances.getAdapterInstancesInfoDto();
// iterate the set
for (AdapterInstanceInfoDto adapter : adapters) {
// print to console
System.out.println(ReflectionToStringBuilder.reflectionToString(adapter, ToStringStyle.MULTI_LINE_STYLE));
}
} catch (Exception e) {
e.printStackTrace();
}
}
and the basicauth object is as follows:
public Builder basicAuth(String username, String password) {
}
The builder class is read only so I can't change basicauth. Any reference or advice would be helpful here.
Just ask for the password before you create the connection.
System.err.print("Username: ");
String user = System.console().readLine();
System.err.print("Password: ");
String password = System.console().readPassword();
try {
Client client = ClientConfig
.builder()
.serverUrl("https://vrops-ip-address/suite-api")
.basicAuth(username, password)
.verify("false")
.useJson()
.build()
.newClient();
.
.
.

Establishing a WebSocket client connection in Jetty?

I'm following this tutorial to establish a WebSocket connection to a server:
http://www.eclipse.org/jetty/documentation/current/jetty-websocket-client-api.html
The code (same as the tutorial):
import java.net.URI;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
/**
* Example of a simple Echo Client.
*/
public class SimpleEchoClient {
public static void main(String[] args) {
String destUri = "ws://echo.websocket.org";
if (args.length > 0) {
destUri = args[0];
}
WebSocketClient client = new WebSocketClient();
SimpleEchoClient socket = new SimpleEchoClient();
try {
client.start();
URI echoUri = new URI(destUri);
ClientUpgradeRequest request = new ClientUpgradeRequest();
client.connect(socket, echoUri, request);
System.out.printf("Connecting to : %s%n", echoUri);
// socket.awaitClose(5, TimeUnit.SECONDS);
} catch (Throwable t) {
t.printStackTrace();
} finally {
try {
client.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Errors:
2014-08-07 21:49:00.346:INFO::main: Logging initialized #86ms
org.eclipse.jetty.websocket.api.InvalidWebSocketException:
SimpleEchoClient is not a valid WebSocket object.
Object must obey one of the following rules:
(1) class implements org.eclipse.jetty.websocket.api.WebSocketListener or
(2) class is annotated with #org.eclipse.jetty.websocket.api.annotations.WebSocket
at org.eclipse.jetty.websocket.common.events.EventDriverFactory.wrap(EventDriverFactory.java:145)
at org.eclipse.jetty.websocket.client.WebSocketClient.connect(WebSocketClient.java:200)
at org.eclipse.jetty.websocket.client.WebSocketClient.connect(WebSocketClient.java:144)
at SimpleEchoClient.main(SimpleEchoClient.java:31)
I'm not too sure what is wrong with my imported jar file. Maybe it is the wrong one? I'm using this: http://mvnrepository.com/artifact/org.eclipse.jetty.websocket/websocket-client/9.2.2.v20140723
Surely there must be an easier way to establish a connection via Jetty Websocket and start receiving data?
As Kayman explained in the comment, your problem with the socket handler implementation, use the latest release here explained with an example(same you used but correct) http://www.eclipse.org/jetty/documentation/current/jetty-websocket-client-api.html
It looks like the documentation is out-of-date with the current version you are using. Try rolling back to a more stable version of 9.2.x like:
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-client</artifactId>
<version>9.2.0.RC0</version>
</dependency>

Categories