I am unable to consume Kafka messages running in a local mode using Apache camel. I am not viewing any Kafka consumer properties when application starts. Below is my Kafka consumer code
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.properties.PropertiesComponent;
import org.apache.camel.impl.DefaultCamelContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class MessageConsumerClient {
private static final Logger LOG = LoggerFactory.getLogger(MessageConsumerClient.class);
private MessageConsumerClient() {
}
public static void main(String[] args) throws Exception {
LOG.info("About to run Kafka-camel integration...");
CamelContext camelContext = new DefaultCamelContext();
// Add route to send messages to Kafka
camelContext.addRoutes(new RouteBuilder() {
public void configure() {
PropertiesComponent pc = getContext().getComponent("properties", PropertiesComponent.class);
pc.setLocation("classpath:application.properties");
log.info("About to start route: Kafka Server -> Log ");
from("kafka:{{consumer.topic}}?brokers={{kafka.host}}:{{kafka.port}}"
+ "&maxPollRecords={{consumer.maxPollRecords}}" + "&consumersCount={{consumer.consumersCount}}"
+ "&seekTo={{consumer.seekTo}}" + "&groupId={{consumer.group}}").routeId("FromKafka")
.log("${body}");
}
});
camelContext.start();
Thread.sleep(5 * 60 * 1000);
camelContext.stop();
}
}
I am using the following dependencies in pom.xml:
1.Camel core - 2.21.1
2.Camel Kafka - 2.21.1
Pom.xml
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>2.21.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-kafka</artifactId>
<version>2.21.1</version>
</dependency>
</dependencies>
Any help would be much appreciated since I am not able to view any logs when executed.
Related
As a RPGLE programmer I was asked to convert an IMAP mail poller to EWS. So I'm a bit out of my comfort zone.
With all documentation I managed to cobble a lot of pieces together, but it looks like I'm missing a vital piece because the program keep crashing at Folder folder = service.bindToFolder(folderId, propertySet);
It first I thought it had something to do with authorization. But then I found a little program EwsEditor at Github which works just fine.
Could someone point me to what I am missing?
With all documentation I managed to cobble a lot of pieces together. My testing code:
package test.ewstest;
import com.microsoft.aad.msal4j.ClientCredentialFactory;
import com.microsoft.aad.msal4j.ClientCredentialParameters;
import com.microsoft.aad.msal4j.ConfidentialClientApplication;
import java.io.File;
import java.io.FileInputStream;
import java.net.URI;
import java.util.Collections;
import java.util.Properties;
import microsoft.exchange.webservices.data.core.ExchangeService;
import microsoft.exchange.webservices.data.core.PropertySet;
import microsoft.exchange.webservices.data.core.enumeration.misc.ConnectingIdType;
import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
import microsoft.exchange.webservices.data.core.enumeration.property.BasePropertySet;
import microsoft.exchange.webservices.data.core.enumeration.property.WellKnownFolderName;
import microsoft.exchange.webservices.data.core.enumeration.search.FolderTraversal;
import microsoft.exchange.webservices.data.core.service.schema.FolderSchema;
import microsoft.exchange.webservices.data.credential.TokenCredentials;
import microsoft.exchange.webservices.data.misc.ImpersonatedUserId;
import microsoft.exchange.webservices.data.property.complex.FolderId;
import microsoft.exchange.webservices.data.property.complex.Mailbox;
import microsoft.exchange.webservices.data.search.FindFoldersResults;
import microsoft.exchange.webservices.data.search.FolderView;
import microsoft.exchange.webservices.data.core.service.folder.Folder;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
public class EwsTest {
static String exchangeUser;
static String exchangeTenant;
static String exchangeClientId;
static String exchangeClientSecret;
static ExchangeService service;
static Logger logger = LogManager.getLogger(EwsTest.class.getName());
static Properties properties = new Properties();
public static void main(String[] args) {
try {
properties.load(new FileInputStream(System.getProperty("user.dir") + File.separator + "EwsTest.properties"));
exchangeUser = properties.getProperty("user");
exchangeTenant = properties.getProperty("tenant");
exchangeClientId = properties.getProperty("client");
exchangeClientSecret = properties.getProperty("secret");
createConnection();
displayFolders();
}
catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
}
static void createConnection() throws Exception {
service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
service.getHttpHeaders().put("X-AnchorMailbox",exchangeUser);
service.getHttpHeaders().put("X-PublicFolderMailbox",exchangeUser);
service.setCredentials(new TokenCredentials(createOauthToken()));
service.setImpersonatedUserId(new ImpersonatedUserId(ConnectingIdType.SmtpAddress, exchangeUser));
service.setUrl(new URI("https://outlook.office365.com/EWS/Exchange.asmx"));
}
static String createOauthToken() throws Exception {
ConfidentialClientApplication app = ConfidentialClientApplication.builder(
exchangeClientId,
ClientCredentialFactory.createFromSecret(exchangeClientSecret))
.authority("https://login.microsoftonline.com/" + exchangeTenant + "/")
.build();
ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(
Collections.singleton("https://outlook.office365.com/.default"))
.build();
return app.acquireToken(clientCredentialParam).get().accessToken();
}
static void displayFolders() throws Exception {
PropertySet propertySet = new PropertySet(BasePropertySet.IdOnly);
propertySet.add(FolderSchema.DisplayName);
FolderView view = new FolderView(100);
view.setPropertySet(propertySet);
view.setTraversal(FolderTraversal.Deep);
Mailbox mailbox = new Mailbox(exchangeUser);
FolderId folderId = new FolderId(WellKnownFolderName.MsgFolderRoot, mailbox);
logger.info("service.bindToFolder");
Folder folder = service.bindToFolder(folderId, propertySet);
logger.info("Ok");
logger.info("service.findFolders");
FindFoldersResults findFolderResults = service.findFolders(folder.getId(), view);
logger.info("Ok");
// find specific folder
for (Folder f : findFolderResults)
{
logger.info(f.getId());
}
}
}
And my Netbeans maven dependencies:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>EwsTest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>javax.xml.ws</groupId>
<artifactId>jaxws-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>msal4j</artifactId>
<version>1.13.3</version>
</dependency>
<dependency>
<groupId>com.microsoft.ews-java-api</groupId>
<artifactId>ews-java-api</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>19</maven.compiler.source>
<maven.compiler.target>19</maven.compiler.target>
<exec.mainClass>test.ewstest.EwsTest</exec.mainClass>
</properties>
</project>
I created my EwsTest.properties file and filled it with the keys:
user=example#example.nl
client=9999x9xx-xx99-x99x-xx99-xx99x9999x9x
tenant=x99x9999-xx99-9999-xx99-9999xx9x9999
secret=XXxxX!9xx-...-
When I run the program, I see that the connection is being build and a token is being exchanged. But it crashes at the statement:
Folder folder = service.bindToFolder(folderId, propertySet);
With an error: The request failed. An internal server error occurred. The operation failed.
microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRequestException: The request failed. An internal server error occurred. The operation failed.
at microsoft.exchange.webservices.data.core.request.SimpleServiceRequestBase.internalExecute(SimpleServiceRequestBase.java:74) ~[ews-java-api-2.0.jar:?]
at microsoft.exchange.webservices.data.core.request.MultiResponseServiceRequest.execute(MultiResponseServiceRequest.java:158) ~[ews-java-api-2.0.jar:?]
at microsoft.exchange.webservices.data.core.ExchangeService.bindToFolder(ExchangeService.java:504) ~[ews-java-api-2.0.jar:?]
at test.ewstest.EwsTest.displayFolders(EwsTest.java:91) ~[classes/:?]
at test.ewstest.EwsTest.main(EwsTest.java:49) [classes/:?]
Caused by: microsoft.exchange.webservices.data.core.exception.service.remote.ServiceResponseException: An internal server error occurred. The operation failed.
at microsoft.exchange.webservices.data.core.request.ServiceRequestBase.processWebException(ServiceRequestBase.java:548) ~[ews-java-api-2.0.jar:?]
at microsoft.exchange.webservices.data.core.request.ServiceRequestBase.validateAndEmitRequest(ServiceRequestBase.java:641) ~[ews-java-api-2.0.jar:?]
at microsoft.exchange.webservices.data.core.request.SimpleServiceRequestBase.internalExecute(SimpleServiceRequestBase.java:62) ~[ews-java-api-2.0.jar:?]
... 4 more
I tried several folders like inbox and root but they all give that same error:
FolderId folderId = new FolderId(WellKnownFolderName.MsgFolderRoot, mailbox);
But since EwsEditor seems to work, I'm clearly missing something. I tried looking at the code of EwsEditor but that's C# which is even harder to understand for me.
i am trying to embed a HTTP-Server into an existing java Application. My goal is to create a small rest API as an interface to send commands to the server application it runs in.
I planned using Jakarta and Jersey 3 with Jetty as embeded HTTP-Server. My starting point was the following topic which was for Jersey 2 but i tried my luck: Embed jersey in java application
My problem is that i get 404 Not Found back when i try to call http://localhost/login/status in my browser. The page is blank. When i switch to using Grizzly2 as embedded HTTP-Server and type the url in the browser, the result is the same. The only difference in Grizzly2 i could spot is when i only call http://localhost/ i get an error page additionally to the 404 Not Found response back. As soon as i add /login to the url, i get the 404 Not Found response without an error page. What could be the reason the server does not pick up my resources?
I am using the Eclipse IDE. First i created a clean Maven project, added the following dependencies and created my test code:
org.glassfish.jersey.core -> jersey-server
org.glassfish.jersey.containers -> jersey-container-jetty-http
On my first startup i got some missing class errors, searched for the dependencies they are in and added them to the pom. Following is my current test code.
<!-- pom.xml -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test-ee</groupId>
<artifactId>test-ee-embed</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>3.0.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-bom</artifactId>
<version>3.0.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jetty-http</artifactId>
</dependency>
</dependencies>
</project>
// LoginserverRestApi.java
package de.l2d;
import org.glassfish.jersey.server.ResourceConfig;
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
#ApplicationPath("/login")
public class LoginserverRestApi extends ResourceConfig {
#GET #Path("/status")
public String status() {
// TODO Return real server statistics.
return "{\"status\":\"ok\"}";
}
}
// RestApiServer.java
package de.l2d;
import java.net.URI;
import org.eclipse.jetty.server.Server;
import org.glassfish.jersey.jetty.JettyHttpContainerFactory;
import jakarta.ws.rs.core.UriBuilder;
public class RestApiServer {
private Server server;
private RestApiServer() {
URI baseUri = UriBuilder.fromUri("http://localhost/").build();
server = JettyHttpContainerFactory.createServer(baseUri, new LoginserverRestApi(), false);
}
public void start() throws Exception {
server.start();
}
public void stop() throws Exception {
server.stop();
}
private static final class SingletonHolder {
protected static RestApiServer instance = new RestApiServer();
}
public static RestApiServer getInstance() {
return SingletonHolder.instance;
}
}
// Main.java
package de.l2d;
public class Main {
public static void main(String[] args) throws Exception {
RestApiServer.getInstance().start();
Thread.currentThread().join();
RestApiServer.getInstance().stop();
}
}
I found the solution to my problem. However, i do not know why it behaves like this.
I had to use the Path annotation instead of the ApplicationPath annotation on the LoginserverRestApi class and additionally construct a ResourceConfig with LoginserverRestApi.class as parameter and pass that Object to the JettyHttpContainerFactory.createServer static method. Following are the two files which differ from the initial post:
// LoginserverRestApi.java
package de.l2d;
import org.glassfish.jersey.server.ResourceConfig;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
#Path("/login")
public class LoginserverRestApi extends ResourceConfig {
#GET #Path("/status")
public String status() {
// TODO Return real server statistics.
return "{\"status\":\"ok\"}";
}
}
// RestApiServer.java
package de.l2d;
import java.net.URI;
import org.eclipse.jetty.server.Server;
import org.glassfish.jersey.jetty.JettyHttpContainerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import jakarta.ws.rs.core.UriBuilder;
public class RestApiServer {
private Server server;
private RestApiServer() {
URI baseUri = UriBuilder.fromUri("http://localhost/").build();
ResourceConfig config = new ResourceConfig(LoginserverRestApi.class);
server = JettyHttpContainerFactory.createServer(baseUri, config, false);
}
public void start() throws Exception {
server.start();
}
public void stop() throws Exception {
server.stop();
}
private static final class SingletonHolder {
protected static RestApiServer instance = new RestApiServer();
}
public static RestApiServer getInstance() {
return SingletonHolder.instance;
}
}
I am following many examples of serenity bdd testing API. Mainly (https://github.com/serenity-bdd/serenity-core/blob/master/serenity-screenplay-rest/src/test/java/net/serenitybdd/screenplay/rest/examples/WhenRetrievingUserDetails.java)
But when I run my code I am always getting:
TEST FAILED WITH ERROR: User attempts to recover the password
---------------------------------------------------------------------
[main] ERROR net.serenitybdd.core.Serenity - TEST FAILED AT STEP Rest
[main] ERROR net.serenitybdd.core.Serenity - SERENITY_DISABLE_REST_CALLS_AFTER_FAILURES
net.serenitybdd.core.exceptions.SerenityManagedException: SERENITY_DISABLE_REST_CALLS_AFTER_FAILURES
at net.serenitybdd.rest.utils.RestExecutionHelper.restCallsAreDisabled(RestExecutionHelper.java:28)
at net.serenitybdd.rest.utils.RestSpecificationFactory.getInstrumentedRequestSpecification(RestSpecificationFactory.java:105)
at net.serenitybdd.rest.utils.RestDecorationHelper.decorate(RestDecorationHelper.java:20)
at net.serenitybdd.rest.SerenityRest.given(SerenityRest.java:220)
at net.serenitybdd.screenplay.rest.interactions.RestInteraction.rest(RestInteraction.java:32)
at net.serenitybdd.screenplay.rest.interactions.Post$$EnhancerByCGLIB$$6437c6d9.CGLIB$rest$3(<generated>)
at net.serenitybdd.screenplay.rest.interactions.Post$$EnhancerByCGLIB$$6437c6d9$$FastClassByCGLIB$$49fc3d71.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at net.thucydides.core.steps.BaseMethodRunner.invokeMethod(BaseMethodRunner.java:10)
at net.thucydides.core.steps.NormalMethodRunner.invokeMethodAndNotifyFailures(NormalMethodRunner.java:20)
at net.thucydides.core.steps.StepInterceptor.runNormalMethod(StepInterceptor.java:361)
at net.thucydides.core.steps.StepInterceptor.testStepResult(StepInterceptor.java:132)
at net.thucydides.core.steps.StepInterceptor.intercept(StepInterceptor.java:68)
at net.serenitybdd.screenplay.rest.interactions.Post$$EnhancerByCGLIB$$6437c6d9.rest(<generated>)
at net.serenitybdd.screenplay.rest.interactions.Post.performAs(Post.java:24)
at net.serenitybdd.screenplay.rest.interactions.Post$$EnhancerByCGLIB$$6437c6d9.CGLIB$performAs$0(<generated>)
at net.serenitybdd.screenplay.rest.interactions.Post$$EnhancerByCGLIB$$6437c6d9$$FastClassByCGLIB$$49fc3d71.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at net.thucydides.core.steps.StepInterceptor.invokeMethod(StepInterceptor.java:449)
at net.thucydides.core.steps.StepInterceptor.executeTestStepMethod(StepInterceptor.java:434)
at net.thucydides.core.steps.StepInterceptor.runTestStep(StepInterceptor.java:409)
at net.thucydides.core.steps.StepInterceptor.runOrSkipMethod(StepInterceptor.java:150)
at net.thucydides.core.steps.StepInterceptor.testStepResult(StepInterceptor.java:137)
at net.thucydides.core.steps.StepInterceptor.intercept(StepInterceptor.java:68)
at net.serenitybdd.screenplay.rest.interactions.Post$$EnhancerByCGLIB$$6437c6d9.performAs(<generated>)
at net.serenitybdd.screenplay.Actor.perform(Actor.java:100)
at net.serenitybdd.screenplay.Actor.attemptsTo(Actor.java:84)
at jarv.serenity.carnival.features.steps.steps.RecoverUserNameSteps.he_attemps_to_recover_password(RecoverUserNameSteps.java:40)
at ✽.he sends the required information to recover his password(src/test/resources/features/ProfileManagement.feature:7)
I have the following test steps:
package jarv.serenity.carnival.features.steps.steps;
import net.serenitybdd.screenplay.rest.abilities.CallAnApi;
import net.serenitybdd.screenplay.rest.interactions.Post;
import cucumber.api.java.Before;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import net.serenitybdd.screenplay.Actor;
import static org.hamcrest.Matchers.equalTo;
import static net.serenitybdd.screenplay.rest.questions.ResponseConsequence.seeThatResponse;
public class RecoverUserNameSteps {
private String theRestApiBaseUrl = "https://www.carnival.com/ProfileManagement/api/v1.0";
private Actor jorge;
private String userName;
#Before
public void set_the_test(){
jorge = Actor.named("Jorge, learning serenity rest").whoCan(CallAnApi.at(theRestApiBaseUrl));
}
#Given("^Jorge is not a registered user$")
public void jorge_is_not_registered() throws Throwable {
//TODO: Investigate what should be done here???
}
#Given("^he wants to recover his password$")
public void jorge_wants_to_recover_the_password() throws Throwable {
//I am setting this as blank cause the service to retrieve the password will only failed if request parameter is blank!!!
//When sending any other kind of string response is 202 Accepted, only blanks generate 400 Bad request
//Test may need to be changed to recover username instead, which has more options to get the error code
userName = "";
}
#When("^he sends the required information to recover his password$")
public void he_attemps_to_recover_password() throws Throwable {
//TODO: Create Object Model for Request Body and send it. Anyway example is way too simple to do that and I am running out of time Julian.
jorge.attemptsTo(
Post.to("/Accounts/Password/Forgot")
.with(request -> request.header("Content-Type", "application/json")
.body("{\"username\": \"joe\"}")
)
);
}
#Then("^he should be informed that operation could not be done$")
public void he_must_see_a_failed_response() throws Throwable {
jorge.should(
seeThatResponse( "Recover for password was denied",
response -> response.statusCode(400)
)
);
}
}
This is my maven with rest related dependencies
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-rest-assured</artifactId>
<version>2.0.34</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-screenplay-rest</artifactId>
<version>2.0.34</version>
<scope>test</scope>
</dependency>
This is my fork git hub repo: https://github.com/jarvcol/CarnivalTest/tree/addApiTesting
Any idea on this???
Because you are not using the matching serenity-core dependency. Try adding following dependency in pom.xml and update project:
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-core</artifactId>
<version>2.0.34</version>
</dependency>
Per my understanding RXJava works within a single JVM. Is there a wrapper/lib/api to support clustered environments with combination of distributed cache, JMS or any other queue to provide subscribers scale across distributed environments? Would like to check here before reinvent the wheel.
You can deploy Vertx instances in a cluster and use RxJava over it. The idea is use EventBus as a transport layer and subscribe to the messages using RxJava. It's not a pure RxJava solution.
A very simple runnable example:
package com.example;
import java.util.concurrent.TimeUnit;
import io.reactivex.Flowable;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.VertxOptions;
import io.vertx.core.json.JsonObject;
import io.vertx.core.spi.cluster.ClusterManager;
import io.vertx.reactivex.core.AbstractVerticle;
import io.vertx.reactivex.core.Vertx;
import io.vertx.reactivex.core.eventbus.EventBus;
import io.vertx.spi.cluster.hazelcast.HazelcastClusterManager;
public class MainVerticle extends AbstractVerticle {
String nodeId;
static final String CENTRAL = "CENTRAL";
#Override
public void start() throws Exception {
EventBus eventBus = vertx.eventBus();
JsonObject config = config();
String nodeID = config.getString("nodeID");
eventBus.consumer(CENTRAL).toFlowable()
.map(msg -> (JsonObject) msg.body())
.filter(msgBody -> !msgBody.getString("sender", "").equals(nodeID))
.subscribe(msgBody -> {
System.out.println(msgBody);
});
Flowable.interval(1, TimeUnit.SECONDS)
.subscribe(tick -> {
JsonObject msg = new JsonObject()
.put("sender", nodeID)
.put("msg", "Hello world");
eventBus.publish(CENTRAL, msg);
});
}
public static void main(String[] args) {
ClusterManager clusterManager = new HazelcastClusterManager();
VertxOptions options = new VertxOptions().setClusterManager(clusterManager);
Vertx.rxClusteredVertx(options)
.doOnError(throwable -> throwable.printStackTrace())
.subscribe(vertx -> {
if (vertx.isClustered()) {
System.out.println("Vertx is running clustered");
}
String nodeID = clusterManager.getNodeID();
System.out.println("Node ID : " + nodeID);
String mainVerticle = MainVerticle.class.getCanonicalName();
DeploymentOptions deploymentOptions = new DeploymentOptions();
deploymentOptions.setConfig(new JsonObject().put("nodeID", nodeID));
vertx.rxDeployVerticle(mainVerticle, deploymentOptions).subscribe();
});
}
}
Maven dependencies:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>rxjava2-clustered</artifactId>
<version>0.42</version>
<packaging>jar</packaging>
<name>rxjava2-clustered</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-rx-java2</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-hazelcast</artifactId>
<version>3.5.0</version>
</dependency>
</dependencies>
</project>
In this example, I am using Hazelcast ClusterManager. There exists implementations for Infinispan, Apache Ignite and Apache Zookeeper. Refer to documentation for full reference:
I am trying to benchmark an application running in the Cloud with JMeter. The underlying protocol uses websockets, but there are some proprietary libraries that I need to use to make those calls. I looked at some websocket plugins for JMeter. But more than just testing I want to use the ability of JMeter to be able to make distributed load generation for my server. I would like to use my own client (written in Java) to make the actual request for the server. Is this some how possible?
There are different implementations of WebSocket Client API, i.e. Jetty Websocket API or Java API for WebSocket
Recently I've been investigating on how WebSockets can be tested using JMeter Load Testing Cloud Solution. Kindly see proof of concept details below. It's using JavaSamplerClient API so extension being packaged as a .jar and put under JMeter Classpath will be available as Java Request Sampler.
First of all you'll need Tyrus – open source JSR-356 implementation. Tyrus requires Java 7 so make sure that you use Java SE 7 to build and execute the extension. The most convenient way of getting dependencies is using following Apache Maven configuration file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>blazemeter-websocket</groupId>
<artifactId>blazemeter-websocket</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-client-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-client</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-container-grizzly</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
</project>
Invokation of target “mvn dependency:copy-dependencies” will download all required jars into /target/dependency folder. However you may with to continue with build, package, etc. maven plugins.
Source code of the extension is follows:
package com.blazemeter;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import org.glassfish.tyrus.client.ClientManager;
import javax.websocket.*;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
#ClientEndpoint
public class BlazemeterWebsocketRequest extends AbstractJavaSamplerClient {
private static String ws_uri;
private static String ws_message;
private static String response_message;
private static CountDownLatch latch;
private static final Logger log = LoggingManager.getLoggerForClass();
#Override
public Arguments getDefaultParameters() {
Arguments params = new Arguments();
params.addArgument("URI", "ws://echo.websocket.org");
params.addArgument("Message", "Blazemeter rocks!");
return params;
}
#Override
public void setupTest(JavaSamplerContext context) {
ws_uri = context.getParameter("URI");
ws_message = context.getParameter("Message");
}
#Override
public SampleResult runTest(JavaSamplerContext javaSamplerContext) {
SampleResult rv = new SampleResult();
rv.sampleStart();
latch = new CountDownLatch(1);
ClientManager client = ClientManager.createClient();
try {
client.connectToServer(BlazemeterWebsocketRequest.class, new URI(ws_uri));
latch.await(1L, TimeUnit.SECONDS);
} catch (Throwable e) {
throw new RuntimeException(e);
}
rv.setSuccessful(true);
rv.setResponseMessage(response_message);
rv.setResponseCode("200");
if (response_message != null) {
rv.setResponseData(response_message.getBytes());
}
rv.sampleEnd();
return rv;
}
#OnOpen
public void onOpen(Session session) {
log.info("Connected ... " + session.getId());
try {
session.getBasicRemote().sendText(ws_message);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#OnMessage
public String onMessage(String message, Session session) {
log.info("Received ... " + message + " on session " + session.getId());
response_message = message;
try {
session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE,""));
} catch (IOException e) {
e.printStackTrace();
}
return response_message;
}
#OnClose
public void onClose(Session session, CloseReason closeReason) {
log.info(String.format("Session %s close because of %s", session.getId(), closeReason));
}
}
Hope this helps,
D.