Micronaut + Vertx + testcontainers - vert.x

How do I configure Micronaut app using Vert.x and testcontainers? I'm trying:
application-test.yml
datasources:
default:
url: jdbc:tc:mysql:8:///db
driverClassName: org.testcontainers.jdbc.ContainerDatabaseDriver
vertx:
mysql:
client:
uri: jdbc:tc:mysql:8:///db
Tests with micronaut-data-jdbc work, but with micronaut-vertx-mysql-client not work:
Error:
Message: Cannot parse invalid connection URI: jdbc:tc:mysql:8:///db
I'm not very familiar with testecontainers, but it seems like it doesn't come up with a fixed port, so I don't know how to configure the connection URI.
Thanks!

It might be a problem that micronaut-vertx-mysql-client does not support the Testcontainers JDBC URL scheme (hard to say without further logs).
In this case, I would suggest to use Testcontainers with database container objects instead of the special JDBC URL.

I got a solution to the problem:
Micronaut + jdbc hikari + vertx mysql client + flyway mysql
package br.com.app;
import io.micronaut.context.ApplicationContext;
import io.micronaut.context.env.PropertySource;
import io.micronaut.core.util.CollectionUtils;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.client.HttpClient;
import io.micronaut.runtime.EmbeddedApplication;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
#Testcontainers
class AuthTest {
static Logger log = LoggerFactory.getLogger(AuthTest.class.getName());
#Container
static MySQLContainer mysql = new MySQLContainer("mysql:8");
private HttpClient client;
private static EmbeddedApplication application;
private static ApplicationContext context;
#BeforeAll
public static void initTests(){
log.info("Mysql is running {}, port {}", mysql.isRunning(), mysql.getFirstMappedPort());
var port = mysql.getFirstMappedPort();
var host = mysql.getHost();
var database = mysql.getDatabaseName();
var user = mysql.getUsername();
var password = mysql.getPassword();
var url = String.format("jdbc:mysql://%s:%s/%s", host, port, database);
application = ApplicationContext.run(EmbeddedApplication.class,
PropertySource.of(
"test",
CollectionUtils.mapOf(
"vertx.mysql.client.port", port,
"vertx.mysql.client.host", host,
"vertx.mysql.client.database", database,
"vertx.mysql.client.user", user,
"vertx.mysql.client.password", password,
"datasources.default.url", url,
"datasources.default.username", user,
"datasources.default.password", password,
"flyway.datasources.default.enabled", true
)
));
context = application.getApplicationContext();
}
#BeforeEach
void beforeEach(){
this.authService = context.getBean(AuthService.class);
this.client = context.getBean(HttpClient.class);
}
#Test
void testItWorks() {
Assertions.assertTrue(application.isRunning());
}
// api tests
}
Help links:
https://dev.to/major13ua/micronaut-integration-testing-using-testcontainers-2e30
https://github.com/major13ua/micronaut-tc/blob/main/src/test/java/com/example/testcontainer/controller/DemoControllerTest.java

Related

Unable to start Appium server programmatically

I am trying to start the Appium server using Appium service builder but am getting the following error. I tried everything but still get the error.
AppiumTest
io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException: The local appium server has not been started. The given Node.js executable: C:\Program Files\nodejs\node.exe Arguments: [C:\Users\[username]\AppData\Roaming\npm\node_modules\appium\build\lib\main.js, --port, 4723, --address, 127.0.0.1]
at io.appium.java_client.service.local.AppiumDriverLocalService.start(AppiumDriverLocalService.java:191)
package MahiyarAutomation;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import org.testng.annotations.Test;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.options.UiAutomator2Options;
import io.appium.java_client.service.local.AppiumDriverLocalService;
import io.appium.java_client.service.local.AppiumServiceBuilder;
public class AppiumBasics {
#Test
public void AppiumTest() throws MalformedURLException
{
AppiumDriverLocalService service = new AppiumServiceBuilder().withAppiumJS(new File("C:\\Users\\mahiyarwadia\\AppData\\Roaming\\npm\\node_modules\\appium\\build\\lib\\main.js"))
.withIPAddress("127.0.0.1").usingPort(4723).build();
service.start();
UiAutomator2Options options = new UiAutomator2Options();
options.setDeviceName ("MahiyarPhone");
options.setApp ("//Users//mahiyarwadia//eclipse-workspace//Appium//src//test//java//resources//ApiDemos-debug.apk");
}
}
Could you try the following?
AppiumServiceBuilder builder = new AppiumServiceBuilder()
.withAppiumJS(new File("C:\\Users\\mahiyarwadia\\AppData\\Roaming\\npm\\node_modules\\appium\\build\\lib\\main.js"))
.withIPAddress("127.0.0.1")
.usingPort(4723);
AppiumDriverLocalService service = AppiumDriverLocalService.buildService(builder);
service.start();
If it still does not work:
Are you able to start the server via the GUI or command line?
Is the Appium path correct?

Mutual Authentication in Scala with Akka

I would create a TLS Session in Scala using Akka with mutual authentication between a client and a server. I have created two CA certificate that have to trust the respective certificates incoming from the other part.
Could you give me an exemple of how implement this?
Thank you.
I created a github project which demonstrates mutual authentication with different kind of clients, including Akka. Please have a look here: https://github.com/Hakky54/mutual-tls-ssl
It contains a full example of loading the ssl material into the client and server
A summary what you need to do is:
For the client
Create a key and a certificate and load it into a keystore
Export the certificate
Create a separate keystore for trusted certificates and import server certificate
Load the two keystores into your http client
For the server
Create a key and a certificate and load it into a keystore
Export the certificate
Create a separate keystore for trusted certificates and import client certificate
Load the two keystores into your server
It is not really clear to me what kind of server you are using, but if you are using spring-boot the example configuration would be:
server:
port: 8443
ssl:
enabled: true
key-store: classpath:identity.jks
key-password: secret
key-store-password: secret
trust-store: classpath:truststore.jks
trust-store-password: secret
client-auth: need
Akka requires a pre-configured instance of SSLContext to be able to configure HTTPS. An example of creating a client with https options would be the code snippet below.
import akka.actor.ActorSystem;
import akka.http.javadsl.ConnectionContext;
import akka.http.javadsl.Http;
import akka.http.javadsl.HttpsConnectionContext;
import com.typesafe.config.ConfigFactory;
import javax.net.ssl.SSLContext;
import java.util.Optional;
class App {
public static void main(String[] args) {
ActorSystem actorSystem = ActorSystem.create(
App.class.getSimpleName(),
ConfigFactory.defaultApplication(App.class.getClassLoader())
);
SSLContext sslContext = ...; //Initialized SSLContext
Http http = Http.get(actorSystem);
HttpsConnectionContext httpsContext = ConnectionContext.https(
sslContext,
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.of(sslContext.getDefaultSSLParameters()));
http.setDefaultClientHttpsContext(httpsContext);
}
}
There are couple of libraries which provides easy to use utility/factory/builder classes to help you to create a SSLContext.
Apache SSLContextBuilder
Jetty SslContextFactory
SSLContext-Kickstart
There could be a bunch other libraries which provide similar functionality, but I am only aware of these three. By the way the sslcontext-kickstart is a library which is maintained by me.
Below is an overview of four ways to load the keystores and create an SSLContext. Vanilla Java and by using the three libraries.
import io.netty.handler.ssl.SslContextBuilder;
import nl.altindag.sslcontext.SSLFactory;
import org.apache.http.ssl.SSLContextBuilder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import javax.net.ssl.*;
import java.io.File;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.Objects;
class SslExample {
public static void main(String[] args) throws Exception {
//Traditional flow of creating sslContext
String keyStorePath = "keystore.p12";
String trustStorePath = "truststore.p12";
char[] keyStorePassword = "secret".toCharArray();
char[] trustStorePassword = "secret".toCharArray();
KeyStore keyStore = KeyStore.getInstance("PKCS12");
KeyStore trustStore = KeyStore.getInstance("PKCS12");
try(InputStream keyStoreInputStream = SslExample.class.getClassLoader().getResourceAsStream(keyStorePath);
InputStream trustStoreInputStream = SslExample.class.getClassLoader().getResourceAsStream(trustStorePath)) {
Objects.requireNonNull(keyStoreInputStream);
Objects.requireNonNull(trustStoreInputStream);
keyStore.load(keyStoreInputStream, keyStorePassword);
trustStore.load(trustStoreInputStream, trustStorePassword);
}
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyStorePassword);
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(keyManagers, trustManagers, new SecureRandom());
//creating sslContext with Apache SSLContextBuilder
SSLContext sslContext1 = SSLContextBuilder.create()
.loadKeyMaterial(new File("keystore.p12"), "secret".toCharArray(), "secret".toCharArray())
.loadTrustMaterial(new File("truststore.p12"), "secret".toCharArray())
.build();
//creating sslContext with Jetty SslContextFactory
SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
sslContextFactory.setKeyStorePath("keystore.p12");
sslContextFactory.setKeyStorePassword("secret");
sslContextFactory.setTrustStorePath("truststore.p12");
sslContextFactory.setTrustStorePassword("secret");
sslContextFactory.start();
SSLContext sslContext2 = sslContextFactory.getSslContext();
//creating sslContext with sslcontext-kickstart
SSLFactory sslFactory = SSLFactory.builder()
.withIdentity("keystore.p12", "secret".toCharArray())
.withTrustStore("truststore.p12", "secret".toCharArray())
.build();
SSLContext sslContext3 = sslFactory.getSslContext();
}
}
It is in java, but IntelliJ Idea provides a handy translate function to scala when pasting the code snippet.

Delete operation is failing to delete a document in mongo using groovy in Jmeter

IAm trying to delete a document i created through my script using deleteone as well as deletemany using following code:
import com.mongodb.client.MongoCollection;
import org.bson.Document;
import static com.mongodb.client.model.Filters.*;
import org.bson.Document;
import org.bson.types.ObjectId;
import java.util.Arrays;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
try {
String mongoUser = vars.get("mongouser");
String userDB = vars.get("userdb");
char[] password = vars.get("password").toCharArray();
MongoCredential credential = MongoCredential.createCredential(mongoUser, userDB, password);
MongoClientSettings settings = MongoClientSettings.builder()
.applyToClusterSettings {builder ->
builder.hosts(Collections.singletonList(new ServerAddress(vars.get("mongohost"), vars.get("mongoPort") as int)))}
.credential(credential)
.build();
MongoClient mongoClient = MongoClients.create(settings);
MongoDatabase database = mongoClient.getDatabase(vars.get("databaseName"));
MongoCollection<Document> collection = database.getCollection(vars.get("collectionName1"));
vars.putObject("collection1", collection);
collection.deleteone(eq("EmployeeName", "Test Automation through Jmeter"));
return "Document deleted";
}
catch (Exception e) {
SampleResult.setSuccessful(false);
SampleResult.setResponseCode("500");
SampleResult.setResponseMessage("Exception: " + e);}
getting this error:
Response message: Exception: groovy.lang.MissingMethodException: No signature of method: com.mongodb.client.internal.MongoCollectionImpl.deleteone() is applicable for argument types: (com.mongodb.client.model.Filters$
SimpleEncodingFilter) values: [Filter{fieldName='EmployeeName', value=Test Automation through Jmeter}]
Possible solutions: deleteOne(org.bson.conversions.Bson), deleteOne(com.mongodb.client.ClientSession, org.bson.conversions.Bson), deleteOne(org.bson.conversions.Bson, com.mongodb.client.model.DeleteOptions), deleteOne(com.mongodb.client.ClientSession, org.bson.conversions.Bson, com.mongodb.client.model.DeleteOptions), deleteMany(org.bson.conversions.Bson), deleteMany(com.mongodb.client.ClientSession, org.bson.conversions.Bson)
What am I doing wrong?
I believe the method is called deleteOne, not deleteone, so the correct way to call it should be:
collection.deleteOne(eq("EmployeeName", "Test Automation through Jmeter"));
See also the javadocs for the MongoCollection: https://mongodb.github.io/mongo-java-driver/3.6/javadoc/?com/mongodb/client/MongoCollection.html

How to externalize mongo db queries

I want to externalize complete mongo db query.
I know that we can externalize by splitting query into $project, $filter ,$sort and so on...
But I want the whole query to be externalized.
For example,
db.employee.find({dept:'FINANCE'},{empId:1,empName:1,empDesn:1}).sort({empSal:1}),
Here I want to externalize this mongo query, please share your thought how to achieve it using java.
I connect to mongodb using java for read and right. We use mongo-java-driver-2-XX.jar to connect it
sample code is :
import com.mongodb.MongoClient;
import com.mongodb.MongoException;
import com.mongodb.WriteConcern;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.DBCursor;
import com.mongodb.ServerAddress;
import java.util.Arrays;
public class MongoDBJDBC{
public static void main( String args[] ){
try{
// To connect to mongodb server
MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
// Now connect to your databases
DB db = mongoClient.getDB( "test" );
System.out.println("Connect to database successfully");
boolean auth = db.authenticate(myUserName, myPassword);
System.out.println("Authentication: "+auth);
}catch(Exception e){
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
}
}
}
For more details check this link

Jersey Grizzly REST service not visible outside localhost

I'm trying to write a REST service in java using Jersey and Glassfish Grizzly. I have a very simple case working internally, but can't seem to call on the server from an external address. I've tried using a variety of different pairs of machines with externally visible IP's, and tried specifying the actual IP address in the server instead of localhost, but nothing works. I'm somewhat loosely following the official user guide here. My resource:
package resources;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
#Path("/simpleREST")
public class SimpleRESTResource
{
#GET
#Produces("text/plain")
public String getMessage()
{
return "Message from server\n";
}
}
And the server:
import java.io.IOException;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.grizzly.http.server.HttpServer;
import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;
import com.sun.jersey.api.core.PackagesResourceConfig;
import com.sun.jersey.api.core.ResourceConfig;
public class Main
{
public static final URI BASE_URI = UriBuilder.fromUri("http://localhost").port(9998).build();
public static void main(String[] args) throws IOException
{
System.out.println("Starting grizzly...");
ResourceConfig rc = new PackagesResourceConfig("resources");
HttpServer myServer = GrizzlyServerFactory.createHttpServer(BASE_URI, rc);
System.out.println(String.format("Jersey app started with WADL available at %s/application.wadl\n" +
"Try out %s/simpleREST\nHit enter to stop it...", BASE_URI, BASE_URI));
System.in.read();
myServer.stop();
}
}
On the same machine, I can successfully interact with the server using
curl -X GET localhost:9998/simpleREST
OR
curl -X GET [external numeric address]:9998/simpleREST
Many thanks in advance for any suggestions.
SOLUTION
I have fixed this problem by setting the server URI to http://0.0.0.0:9998 instead of localhost, 127.0.0.1, or the actual address.
To make a server IP adress visible outside of localhost, you must fist open the neccessary firewall ports(if you have one), or use "0.0.0.0" instead of "localhost" in order for the server to listen to all IP addresses and network adapters. Before testing it in your local network, try pinging your server device from your client device to check if there is an actual connection or if the devices are not connected at all.
With Jersey and Grizzly 2.30, it's simpler:
final ResourceConfig rc = new ResourceConfig().packages("com.rest");
HttpServer httpServer = Grizzly
HttpServerFactory.createHttpServer(URI.create("http://0.0.0.0:9998/api/"), rc);
or, you can try these codes below:
ResourceConfig rc = new PackagesResourceConfig("your-rest-packages");
HttpHandler handler = ContainerFactory.createContainer(HttpHandler.class, rc);
server = new HttpServer();
server.getServerConfiguration().addHttpHandler(handler);
//attach listeners
InetAddress localHost = InetAddress.getLocalHost();
String localHostAddr = localHost.getHostAddress();
NetworkListener localHostListener = new NetworkListener("localhost", localHostAddr, port);
server.addListener(localHostListener);
InetAddress loopback = InetAddress.getLoopbackAddress();
String loopbackAddr = loopback.getHostAddress();
NetworkListener loopbackListener = new NetworkListener("loopback", loopbackAddr, port);
now your server could both list to localhost and loopback