And Todays’s Quote Would Be..

Life begins at the end of your comfort zone.

Neale Donald Walsch

Monitoring Kafka Topics with Dockerized Kafka Manager

Yesterday, Dimas (one of my colleague), are asking me on how to monitor Kafka which are running on top of Openshift using a tools which are accessible thru browser.

One of the tools im recommending is Kafka Manager, which we can download from below url,

https://github.com/yahoo/kafka-manager

Lets start from the beginning, from how to start Zookeeper, Kafka Server, until simulate a simple produce and consume and monitoring it using Kafka Manager.

First, download Kafka from Apache site, extract it, and open bin folder. We need Zookeeper to start before we start anything else. Fyi for this example im using Win10 as my primary Operating System, so all my command below can be different depends on what Operating System you are using.

cd D:\software\kafka_2.13-2.4.0\bin\windows
zookeeper-server-start.bat ..\..\config\zookeeper.properties

And run Kafka Server afterwards,

kafka-server-start.bat ..\..\config\server.properties

Create a topic,

kafka-topics.bat --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic my-testing-topic

Try produce a simple echo message using Kafka Producer,

kafka-console-producer.bat --broker-list localhost:9092 --topic my-testing-topic

And listen to the sent message using Kafka Consumer,

kafka-console-consumer.bat --bootstrap-server localhost:9092 -topic  my-testing-topic --from-beginning

If you only want to get all the new message, ignoring the old one, just remove “–from-beginning” parameter. And use “–offset” parameter to get a specific offset.

Next is running my Kafka Manager using Docker command. Fyi, 192.168.1.20 is my laptop ip.

docker run --network host --add-host=moby:192.168.1.20 --add-host DESKTOP:192.168.1.20 -p 9000:9000 -e ZK_HOSTS="192.168.1.20:2181"  kafkamanager/kafka-manager

After Kafka-Manager is successfully started, we can browse our Kafka by opening thru browser,

Google+

Does JBoss EAP’s “org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker” doing a “Select 1 from Dual”?

TL;DR
No it is NOT.

Longer Version :
JBoss EAP and Wildfly have its own internal query validator to check whether connection is active or not before doing connection to Oracle database, it resides on below class.

org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker

Why i’m interested in OracleValidConnectionChecker class? Because several days ago, i got a critical question from Habiburrokhman Sjarbini, my fellow RedHat Platform Consultant regarding this. Whether OracleValidConnectionChecker which is embedded in JBoss EAP will do a “select 1 from dual” query?

I have to decompile a lot of classes to see what is running under the hood,

Here is the screenshot of what OracleValidConnectionChecker looks like,

On Oracle database, it will call “oracle.jdbc.driver.OracleConnection” and invoke method “pingDatabase”. Lets check what is the content of “pingDatabase” method,

OracleConnection will call its super class, OracleConnectionWrapper, and invoke pingDatabase method. It goes here and there, until finally it reach oracle.jdbc.driver.PhysicalConnection class on method doPingDatabase.

And as you can see, it runs a “SELECT ‘x’ FROM DUAL” query, instead on “select 1 from dual”. :)

Jar versions :

ojdbc8.jar
ironjacamar-jdbc-1.4.11.Final.jar
Google+

Removing Bucket Name as Subdomain when Using AmazonS3Client Android Library

On a simple java desktop app, uploading an image to an S3-compliant API service is so simple. Each bucket are represented as folders, therefore no special approach is needed. Here is how it was done,

public AWSTestCase() {
	AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration("http://localhost:8082/", "us-west-2");
	client = AmazonS3ClientBuilder.standard()
			.withPathStyleAccessEnabled(true)
			.withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials()))
			.withEndpointConfiguration(endpoint)
			.withClientConfiguration(new ClientConfiguration().withProtocol(Protocol.HTTP))
			.enablePathStyleAccess()
			.build();
}

@Test
public void testUploadToBucket() {
	client.putObject("bucket01", "jim.png", new File("d:\\jim.png"));
}

It will try to upload to below url,

http://localhost:8082/bucket01

But the same approach is not working on Android,

File file = new File(Environment.getExternalStorageDirectory(), attachmentModel.getLocalPath());

AWSCredentials credentials = new BasicAWSCredentials(ConstantCommon.ACCESS_KEY, ConstantCommon.SECRET_KEY);
ClientConfiguration clientConfig = new ClientConfiguration();
clientConfig.setProtocol(Protocol.HTTP);

AmazonS3Client client = new AmazonS3Client(credentials, clientConfig);
client.setEndpoint("http://localhost:8082/");
client.putObject("bucket01", attachmentModel.getRemotePath(), file);

It will gives error,

com.amazonaws.AmazonClientException: Unable to execute HTTP request: bucket01.localhost

Somehow app will try to upload to below url, because bucket name are treated as subdomain.

http://bucket01.localhost:8082/

Workaround is quite easy, setting bucket name as empty string and set bucket name as folder on endpoint should solve this issue.

public AWSTestCase() {
	client = new AmazonS3Client(new AnonymousAWSCredentials());
	client.setEndpoint("http://localhost:8082/bucket01");
}

@Test
public void testUploadToBucket() {
	client.putObject("", "jim.png", new File("d:\\jim.png"));
}

The content of my Gradle file,

    implementation 'com.amazonaws:aws-android-sdk-s3:2.9.2'
    implementation 'com.amazonaws:aws-android-sdk-core:2.16.5'
Google+

Slowness when Generating SecureRandom with Java on RHEL 7

Today i had a very weird issue where there is slowness on my app when generating random secure number on my server, the weird thing is that it never happen on my Windows machine. After intensive debugging i found out that below code part is causing the slowness,

    static {
        try {
            secureRandom = SecureRandom.getInstanceStrong();
        } catch (Exception e) {
            secureRandom = new SecureRandom();
        }
    }

Replacing it with below code solve my problem,

    static {
        try {
            secureRandom = SecureRandom.getInstance("SHA1PRNG");
        } catch (Exception e) {
            secureRandom = new SecureRandom();
        }
    }
Google+

Deploying Spring Boot with A Dynamic application.properties Location to Openshift

I want to create a simple spring boot app, and deploy it to Openshift 4.2. It supposed to be a straigh forward task, but the problem is that it is required to externalize all configuration to a configmaps or secret so no need to recompile the whole app in case of configuration change.

There are several approach of externalizing configuraton to configmaps, one way is put it as a string literal, include on your pod and call on application via environment variables, or deploy the whole configuration file and mount it on your Openshift pod. The last approach is the one that we will be doing now today.

First lets start with deploying our properties to Openshift as configmaps,

oc create cm myapp-api-configmap --from-file=D:\source\my-app\src\main\resources\application.properties

We can check and validate the result,

oc get cm

oc describe cm myapp-api-configmap

After that, we can mount corresponding configmap to a specific folder on our Pod, on below example modification is done on DeploymentConfig.yaml and mounting application.properties to /deployments/config folder.

kind: DeploymentConfig
apiVersion: apps.openshift.io/v1
metadata:
  ........
    spec:
      volumes:
        - name: myapp-api-configmap-volume
          configMap:
            name: myapp-api-configmap
            defaultMode: 420
      containers:
        - name: myapp-api
          image: >-
            image-registry.openshift-image-registry.svc:5000/openshift/myapp@sha256:1127.....
          ports:
            - containerPort: 8778
              protocol: TCP
            - containerPort: 8080
              protocol: TCP
            - containerPort: 8443
              protocol: TCP
          resources: {}
          volumeMounts:
            - name: myapp-api-configmap-volume
              mountPath: /deployments/config
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: Always
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      dnsPolicy: ClusterFirst
      securityContext: {}
      schedulerName: default-scheduler

A modification is also needed on my Dockerfile, pointing a new path for my properties file by using “spring.config.location” parameter,

FROM registry.access.redhat.com/openjdk/openjdk-11-rhel7

USER jboss
RUN mkdir -p /deployments/image && chown -R jboss:0 /deployments
EXPOSE 8080

COPY target/application-1.0.jar /deployments/application.jar
CMD ["java", "-jar", "/deployments/application.jar", "--spring.config.location=file:///deployments/config/application.properties"]

Build, deploy,and see that application is now taking configuration from external configuration file.

Google+