Dropwizard as a non blocking task execution component - java

I'm in the process of evaluating dropwizard for a mission critical component of our production system.
What I need to implement is a command line tool with RESTful support(there is little need to provide REST API, I need mostly to communicate with external API systems for B2B), logging dependency injection and some short of non blocking I/O operations for maximum performance.
My question is if someone has experience with the particular framwork being ready for a production system and some alternative solutions of a lightweight non blocking operations (Something like Celery on Python)
Finally, does Dropwizard supports java 1.8?
Many thanks for the help in advance

dropwizard-sundial lets you schedule jobs in dropwizard. The github README has more sample but here's a quick sneak peak:
#CronTrigger(cron = "0/5 * * * * ?")
public class SampleJob extends org.knowm.sundial.Job {
#Override
public void doRun() throws JobInterruptException {
// Do something interesting...
}
}
What it does is at the time of initializing your dropwizard application, sundial will drop in and start its scheduler. Then you can configure tasks via package in yaml, tasks, xml. Also the admin task it registed could be used to manage jobs (create/trigger/etc).
One thing to notice is that dropwizard-sundial package itself includes a set of dropwizard-core and dropwizard-util. Very likely you'll find it conflicts with the version which would cause NoClassDefException or NoMethodFoundException. My solution is to exclude from dropwizard-sundial and use your own one.
<dependency>
<groupId>org.knowm</groupId>
<artifactId>dropwizard-sundial</artifactId>
<version>1.0.0.0</version>
<exclusions>
<exclusion>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-core</artifactId>
</exclusion>
<exclusion>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-util</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
</exclusion>
</exclusions>
</dependency>

Related

Httpclient and Zipkin Java

My and project team are looking to add Zipkin logging and tracing to our current project. We are working in an microservice environment using Spring Boot (Java 17) and cloud foundery. For the communication between Microservices we are using HttpClient. From what I've gathered from the documentation Zipkin requires an RestTemplate to function. However we don't have time to change this.
We were able to implement Zipkin in every individual project. However, every call generates their own Trace ID. I think we need to configure the HttpClient to work in tandem with Zipkin, however the documentation is not very clear and I have been unable to find anything that explains how to do this.
What can I try on this? I've included the config and dependencies below.
spring:
application:
name: Application_1
zipkin:
baseUrl: http://localhost:9411
sleuth:
sampler:
probability: 1.0
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>3.1.3</version>
</dependency>

Classpath issue preventing pipeline to be run on Google Dataflow

I'm new to a project where we have a spring-boot application running on GKE receiving (via Kafka) and publishing events via Pub/Sub. Consumers of these events might want to have these events replayed and we want them to request this via the REST API of our application. Since the application stores the events in GCS before publishing, we thought Apache Beam pipelines run with DataFlow should do the trick.
One "replay request" might result in multiple pipelines, since the events in GCS are stored in folder structures containing the date (e.g. gs://<entity>/2020/12/13/event.json) and depending on how much history the consumer needs, we create a pipeline per day of events.
I'm fairly confident that the logic of defining and submitting pipelines is correct, since the application is able to perform this on a local Kubernetes cluster with the DirectRunner.
On DataFlow I run into the issue summarized here. Spawning a worker (org.apache.beam.runners.dataflow.worker.DataflowBatchWorkerHarness) fails due to a classpath issue:
Caused by: java.lang.NoClassDefFoundError: org/apache/beam/sdk/options/PipelineOptions
I can see that my jar that should have the correct dependencies on the classpath when DataFlow spawns the worker (Omitted most parameters):
java
-cp
/opt/google/dataflow/batch/libshuffle_v1.jar:/opt/google/dataflow/batch/dataflow-worker.jar:/opt/google/dataflow/slf4j/jcl_over_slf4j.jar:/opt/google/dataflow/slf4j/log4j_over_slf4j.jar:/opt/google/dataflow/slf4j/log4j_to_slf4j.jar:/var/opt/google/dataflow/app-6BkavP-0nx4wHMC__85sdbCjJQa7QcQcOxGSQL5huMU.jar
...
org.apache.beam.runners.dataflow.worker.DataflowBatchWorkerHarness
After playing around with different scopes of the beam dependencies, because I suspected a clash with the google-dataflow.jar, I haven't seen any change. I'm a bit clueless on where to continue looking. I'm using beam library version 2.27.0 and these are the ones referred to in my pom.xml:
<dependency>
<groupId>org.apache.beam</groupId>
<artifactId>beam-runners-google-cloud-dataflow-java</artifactId>
<version>${beam.version}</version>
</dependency>
<dependency>
<groupId>org.apache.beam</groupId>
<artifactId>beam-runners-direct-java</artifactId>
<version>${beam.version}</version>
</dependency>
<dependency>
<groupId>org.apache.beam</groupId>
<artifactId>beam-sdks-java-io-google-cloud-platform</artifactId>
<version>${beam.version}</version>
</dependency>
<dependency>
<groupId>org.apache.beam</groupId>
<artifactId>beam-sdks-java-extensions-google-cloud-platform-core</artifactId>
<version>${beam.version}</version>
</dependency>
Any advice is much appreciated.
The class org/apache/beam/sdk/options/PipelineOptions is found in the core Java SDK. The artifact is beam-sdks-java-core. This is not baked in to the Dataflow worker, but is part of the expected staged files.
The DataflowRunner by default will attempt to stage every file that it finds on the classpath. If there is anything about your environment or application that affects its ability to do this, you will need to add the SDK dependency yourself.

Camel AMQP - AMQConnectionFactory ClassNotFound

I'm using Camel 2.13.3 and trying to establish a connection via AMQP to a remote ActiveMQ instance.
According to the Camel AMQP docs is should be sufficient to add the following dependency
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-amqp</artifactId>
<version>2.13.1</version>
</dependency>
It then indicates that you should configure the jms component to use a connection factory supplied by the QPID project. The docs page uses org.apache.qpid.amqp_1_0.jms.impl.ConnectionFactoryImpl, and the results of other google searches indicate that org.apache.qpid.client.AMQConnectionFactory could be used.
However, the org.apache.qpid dependencies do not appear to have been added to the project and, unsurprisingly, I get a ClassNotFoundException when I run it.
I considered downloading the qpid dependency separately, but their web site seems to indicate that the qpid client project has been deprecated and replaced by something else ( QPID Messaging API if I remember correctly )
Can anyone point me in the right direction?
should be sufficient
The Camel docs you linked to does not state that. It just says this dependency is needed, doesn't say anything about additional dependencies. Just looked inside the jar you're using, and it does not contain qpid-client classes. You should add that dependency to your pom as well. For AMQP 0.x, there is a good chance you'll need JMS spec dependency as well:
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-client</artifactId>
<version>0.32</version> <!-- replace with appropriate version -->
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
<version>1.0</version>
</dependency>
If you're using AMQP 1.0,
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-jms-client</artifactId>
<version>0.3.0</version>
</dependency>

How to exchange signals between applications?

I have two unconnected applications. One is the main app that performs the business logic and CRUD on database.
A 2nd app periodically rebuilds a database cache (long running taks). I want to send a signal to the main app when the rebuild starts, and when it's finished, as the main app should take specific actions while rebuilding takes place.
How could I achive this best using spring-boot?
using spring-boot you can use jms simply by adding active-mq dependencies.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-broker</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
</dependency>
in yml config you would start the amq jms broker in one application by not specifying broker-url at all because spring.activemq.in-memory property defaults to true (http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html)
or configuring it like this:
activemq:
broker-url: failover:(vm://localhost:61616?connectionTimeout=3000)
and connect to it from the other application like this
activemq:
broker-url: failover:(tcp://machineoftheotherapplication:61616?connectionTimeout=3000)
You might need to consider if you need your messages to use persistent reliable delivery, meaning if you send a message and the other application is not running it would get the message after it start up again.
If your application works with http requests you could just add a special controller which would process the requests from the second app.
Another option would be a JMX request.
However, security should be considered.

Support for X509PKIPathv1 in xws-security for Spring-WS

I'm trying to send a request to an existing webservice. This webservice is not governed by me. The security policy of this webservice requires me to send my complete certificate chain in my SOAP request. My certificate chain contains 3 certificates. There are no issues with the setup of the certificate chain, as I'm able to test it's validity (and have done so).
The security configuration for this setup (= sending the complete certificate chain in the request), is:
<xwss:Sign id="signature">
<xwss:X509Token
certificateAlias="alias"
keyReferenceType="Direct"
valueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1" />
</xwss:Sign>
I'm trying to achieve this through Spring-WS. Spring-WS uses spring-ws-security for security. Spring-ws-security delegates to xws-security.
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-security</artifactId>
<version>2.1.0.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.apache.ws.security</groupId>
<artifactId>wss4j</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.xml.wsit</groupId>
<artifactId>xws-security</artifactId>
</exclusion>
</exclusions>
</dependency>
Xws-security comes in 2 flavors:
<dependency>
<groupId>com.sun.xml.wsit</groupId>
<artifactId>xws-security</artifactId>
<version>1.3.1</version>
</dependency>
and
<dependency>
<groupId>com.sun.xml.wss</groupId>
<artifactId>xws-security</artifactId>
<version>3.0</version>
</dependency>
The first one is used by Spring WS Security. The second is legacy.
Applying my XWSS configuration in xws-security is done in a class called BinarySecurityToken. BinarySecurityToken has a field called
valueType
The JavaDoc of valueType says it has support for X509PKIPathv1 (among others). However, it does not, as stated by this setter:
protected void setValueType(String valueType) {
if (!(MessageConstants.X509v3_NS.equals(valueType)||MessageConstants.X509v1_NS.equals(valueType))) {
log.log(Level.SEVERE,"WSS0342.valtype.invalid");
throw new RuntimeException("Unsupported value type: " + valueType);
}
this.valueType = valueType;
}
The class MessageConstants does not (even) have a static for X509PKIPathv1. When I run my code, I get the expected result:
Unsupported value type: http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1
I was able to look at the source code of the legacy com.sun.xml.wss.xws-security:3.0. Despite my efforts, I have not found the source code of com.sun.xml.wsit.xws-security-1.3.1. However I believe the code is the same. I tried both libraries and both give me the same exception. I tried it, using the default spring-ws-security and using explicit dependency declarations to both libraries (one at a time).
My questions:
Has anyone been able to use xws-security for generating an X509 signature with a valueType of X509PKIPathv1 and a keyReferenceType that is Direct?
Do other xws-security implementations exist that offer this? Or should I look at a completely different approach like Wss4j?
I have considered re-writing BinarySecurityToken, but that would probably also imply rewriting the X509 signing of SignatureProcessor in DSIG.
Interesting problem you got there.
As far as I could tell with my Google-fu, there exists support for #X509PKIPathv1 in some projects (e.g., Oracle's XMLSec or Open SAML), however it is not widespread and even application like Soap UI don't support it for SOAP-WS.
Not only that, but other languages/frameworks have the same lack of support, like Delphi and .NET, IBM JRE.
What you could do, based on this SO and especially this SO is implementing your own WebServiceTemplate / WebServiceMessageSender.
The valueType can be #X509v3, #X509PKIPathv1
That is found here
XWS-SecurityIntro4
Have you tried those values specifically instead of a URL?
This pull request will enable the ability to use X509PKIPathv1.

Categories