solaceproducts / solace-spring-boot Goto Github PK
View Code? Open in Web Editor NEWAn umbrella project containing all Solace projects for Spring Boot
License: Apache License 2.0
An umbrella project containing all Solace projects for Spring Boot
License: Apache License 2.0
During the next major version we should consider whether or not to update the default connect and probably more importantly the reconnect settings. It seems like they were initially set to the current values b/c of the Developer guide says during a HA failover apps should retry to reconnect for "at least 5 minutes" - and we set the defaults to that minimum. But if reconnecting fails then in many cases your app is just done doing anything productive and we don't automatically stop your app. So unless you are checking the health and telling your app to restart then your app is just running and doing nothing. Because of this I wonder if we should default to a reconnect forever type scenario?
I'm migrating from RabbitMQ to Solace, and there's a feature important in my spring boot applications with the rabbitmq client about metrics. We are using the metric rabbitmq.consumed
to find the rate of consumed messages per second and scaling horizontally after a certain threshold.
I'm able to get this metric because the rabbit client delivers it for me as you can see here: https://blog.rabbitmq.com/posts/2016/11/metrics-support-in-rabbitmq-java-client-4-0/
That said, my question is: The solace client for java (sol-jcsmp) already delivers its metrics? If not, How I can have this metric?
Now a days we have to provide *.p12 files for authentication and five parameters explaining how to use the keystore:
apiProperties:
SSL_KEY_STORE: /somepath/file.jks
SSL_KEY_STORE_FORMAT: JKS
SSL_KEY_STORE_PASSWORD: password1
SSL_PRIVATE_KEY_ALIAS: nameinkeystore
SSL_PRIVATE_KEY_PASSWORD: password2
AUTHENTICATION_SCHEME: AUTHENTICATION_SCHEME_CLIENT_CERTIFICATE
this is not very handy when providing the spring boot / spring cloud stream application as docker container. Because best practice for kubernetes is it to provide secrets as environment variable.
Solace seams to mention this on its own:
Because with sol-jcsmp 10.14.0 there is a new option: SSL_IN_MEMORY_KEY_STORE
This option can not be used in a spring application.yaml file.
There for i propose 2 new options:
apiProperties:
SSL_KEY: <PEM Key>
SSL_TRUST: <List of PEM certs>
Sample code: how to get from x509 to a KeyStore.
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Example code to create a Java keystore from a certificate and a private key.
* <p>
* The example certificate has been created with the following openssl command:
*
* <pre>
* openssl req -new -newkey rsa:2048 -x509 -days 365 -nodes -keyout privatekey.pem -out cert.pem
* </pre>
*/
public class KeystoreBuilder {
/**
* Retrieve this value from configuration.
*/
static final String CERTIFICATE = "-----BEGIN CERTIFICATE-----\n" //
+ "MIICojCCAYoCCQCumQlzsNV9DDANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAh0\n" //
+ "ZXN0LmNvbTAeFw0yMjA3MDYwODUxNThaFw0yMzA3MDYwODUxNThaMBMxETAPBgNV\n" //
+ "BAMMCHRlc3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxozk\n" //
+ "rkbXlye5SKyy6bfUMCFRNeycbATAjWjvLis3YVw38Hj7GbU64NYK/SI2eOFu5cAF\n" //
+ "8ljLbMAyXSTbYA1p0jo2owhmA/hiM4bT9JNrsyMYRUhOnPVM9HWB0I8Yn4D8+i+J\n" //
+ "WBaS0qh42SvCAxhZYn7I9mvpZxaPabfis4fFKXsuRGISYh4GIyTA2ZHgt/MLPBeL\n" //
+ "hqdbmTexs7QtFik5Pl0cby5Mc0eFIbpqWwsfcN3QE74cCfPTronfgiZu7suwRKrw\n" //
+ "lCRZ5OdR6/UogltHCEHi8x5HilxJj2NJJxW0BUUmTXHqLVTjR83lSBYQV8aG24T8\n" //
+ "tEiYj/y0ZmSk1qwMNwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCS8TIfvMBui4uW\n" //
+ "pYoAqvDDYVht+T2sP1zTrg6+V0CSULneTRm5YM9EFwSvyn1Uk7e2p7k0UXPi2moO\n" //
+ "H9h/mr38xG4cJ8pPtzUvq6PmtMmRBMDV+i/nxqXjdzlR4vn03Qq1oD7ayW0t4CIi\n" //
+ "N4SugpGFnsJ88JttjSNeaXWE0m11pyaT5p8WMv11XpU3riNMXiEI2yZHbP7mQUI5\n" //
+ "x6wvQqKGLgBKkVuNiWPTJlLWQxtcaFyQqSusqQMuqmhZQFclZsTEmD+clFY08GAp\n" //
+ "9fPsmNvi9dgLmKSNQ2Hb9F0Tuxw9mDmLJbA/ukgfQwOcElvvTtOxv0Vq5MumNFBS\n" //
+ "UJFQEdAm\n" //
+ "-----END CERTIFICATE-----";
/**
* Retrieve this credential (!) from secure configuration.
*/
static final String PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" //
+ "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDGjOSuRteXJ7lI\n" //
+ "rLLpt9QwIVE17JxsBMCNaO8uKzdhXDfwePsZtTrg1gr9IjZ44W7lwAXyWMtswDJd\n" //
+ "JNtgDWnSOjajCGYD+GIzhtP0k2uzIxhFSE6c9Uz0dYHQjxifgPz6L4lYFpLSqHjZ\n" //
+ "K8IDGFlifsj2a+lnFo9pt+Kzh8Upey5EYhJiHgYjJMDZkeC38ws8F4uGp1uZN7Gz\n" //
+ "tC0WKTk+XRxvLkxzR4UhumpbCx9w3dATvhwJ89Ouid+CJm7uy7BEqvCUJFnk51Hr\n" //
+ "9SiCW0cIQeLzHkeKXEmPY0knFbQFRSZNceotVONHzeVIFhBXxobbhPy0SJiP/LRm\n" //
+ "ZKTWrAw3AgMBAAECggEAVsIoBtMjz4PnHY+BGkleaa2VS+fZLgYhkWkB4n211FA0\n" //
+ "jVp/9mrPkIFXCedSQB3ZlIEE2DHeqeWN3E+HoIAb9mXDjBfWY/O8DWHj6iIk1IEI\n" //
+ "UPXYjBNQDh3unJB6pO/7GuN8s0Yh3/UH4XWScEHKhRR7gdoDgi1Ee2CDqgkwqP/K\n" //
+ "POU6p7vzB9iF1yFtZpcJhI2YcZuu8ZGjFn0bxdg5RW3BYRvlpRCGzAQNUkA4nkp5\n" //
+ "LKhnm5UUxr4XJeOtcfYUAVhkogDqLVzBoxmvXxjYf5uw6Py8xxsXB58Q+gWf9Dik\n" //
+ "5CkpARh2MnqzCer0sCK8/vWAECMHD4+t8LQkLGQ3mQKBgQDp54jBYxoyHdbaXGof\n" //
+ "1OSJQ06kYtG+1z0VnIAqfVfUSC/wN3MvYp8YscCMKxx2QuqLU1esm1ws5/M+64UN\n" //
+ "idGaCf8liBdoKp2cFSnEvXk2lIfLtXsLyZ9aMabe1f/q5GYygMqSBc3MIyEPs2t0\n" //
+ "/5WslBa8n343ZIdH6twJjOt5PQKBgQDZTmYE2ZbAL5L8y8aRTUoiEpwklpJR5W/K\n" //
+ "oy0EYqB3sWVVEDvabjVEMikufOfCwDMMMLXsPHr8/6Z6XQRYsxXe/QMK7xvKhov6\n" //
+ "jJgJgAd6yH1J6aLuezwWyrdlGGT7Ex3bxZdOMYtw+gaZl12/p+aAdTJGbnYx1sAe\n" //
+ "G07r0/0qgwKBgQCuiIvs8YvsdYOKcIbnta3KFqUp2Gr14hm8dIjWK61Lw4mxz05t\n" //
+ "v0ND4+7vKIQWYpws1kWHkG3ZPEKvYoJntbznGip+0OvWWGY+vzPpkBBQf8hMYuCr\n" //
+ "zQjQ/ler0zchCMiRSrTc/OOxPU1AL/sw1D3VBrNokAJYRvUC3ubNYY+baQKBgEYk\n" //
+ "WiXCnjhWotlaZTPNgNpSq3fb6krpBhagaQ17UFSSPCUi4k71N9hVYJmS07Q3GcMb\n" //
+ "jf084G39jxz8HUUMOUkK3gqPd6b9mv06mHColMF7KYXMFj1oJdMth9jn8OBiIUcp\n" //
+ "Fle1Ak9rROoaw7XzWiGosputWBVqPgT5x5WzjYpFAoGBAOiKcQ5iw/dsDhsdbF2c\n" //
+ "7Q+qJyAkGU4WmYN39c6rhJt7rb+vCuhAith6G8uMaD4BuRPMwWre093HAd31pSDR\n" //
+ "1iDp1LNQ0G4MtohmgJgnc/+QXxZxJzvrcLr2QrASlA2DIgtxCek8ltpE6khJi533\n" //
+ "dtKcxdEOiAAaGblmm6mk5YEr\n" //
+ "-----END PRIVATE KEY-----";
static Certificate[] getCertificates(String pem) throws CertificateException, IOException {
var f = CertificateFactory.getInstance("X.509");
try (var is = new ByteArrayInputStream(pem.getBytes(ISO_8859_1))) {
return f.generateCertificates(is).toArray(new Certificate[0]);
}
}
static PrivateKey getPrivateKey(String pem) throws NoSuchAlgorithmException, InvalidKeySpecException {
var f = KeyFactory.getInstance("RSA");
return f.generatePrivate(new PKCS8EncodedKeySpec(decodePEM(pem)));
}
private static Pattern PEM_FORMAT = Pattern.compile("(?m)(?s)^---*BEGIN.*---*$(.*)^---*END.*---*$.*");
private static byte[] decodePEM(String pem) {
Matcher matcher = PEM_FORMAT.matcher(pem);
if (!matcher.matches()) {
throw new IllegalArgumentException("Invalid PEM string");
}
return Base64.getMimeDecoder().decode(matcher.group(1));
}
static KeyStore createKeystore(PrivateKey key, Certificate[] certificates)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
ks.setKeyEntry("certificate", key, "changeit".toCharArray(), certificates);
return ks;
}
public static void main(String[] args) throws Exception {
var certs = getCertificates(CERTIFICATE);
System.out.println(Arrays.toString(certs));
var key = getPrivateKey(PRIVATE_KEY);
System.out.println(key);
KeyStore ks = createKeystore(key, certs);
System.out.println(ks);
}
}
Spring Boot 3.1 has introduced the notion of ConnectionDetails
. You can read more about it this blog post. There's integration for both Testcontainers and Docker Compose where Spring Boot is able to source the details of the connection transparently.
Usually the connection details keep the "url" or "host" of the related server and authentication details. You can browse the Spring Boot code base to get an idea.
If you add support for this here, then @ServiceConnection
would work transparently for Solace and we could even configure it automatically when an entry is created on start.spring.io. To get an idea, select Testcontainers and a supported entry (for instance Postgres). Let me know if I can help.
We should add a Github action job (or update the existing one) to regularly check and test this project against new versions of Spring Boot.
What this probably has to do is just regularly poll Maven Central for any changes to Spring Boot. If a new one is detected, update the action's local repo (doesn't need to actually write to the repo), and run the tests.
If we need to make a new job for this, it would be nice if we could get a separate badge for it on the README if possible.
Hello, I hope you're good!
I would like to know if there have any plan to support Spring Boot 3?
Thank you!
Spring comes with an integrated health indicator.
Here you can see the out of the box list:
Those help for example in an kubernetes/OpenShift context to restart the pod if the broker connections was lost / the session was destroyed).To enshure that the pod is not running without jcsmp session and any possibility to recover this at some point.
Her is the it is a sample health check for JMS:
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/jms/JmsHealthIndicator.java
Would you also provide an HelthIndicator for jcsmp?
I was wondering if SolaceJava
was a keyword of some sort? In the context of Spring Boot, the word "java" feels a bit odd. This is a breaking change though in case users are excluding the auto-configuration with the class name.
I suggest SolaceAutoConfiguration
. I'd also replace SolaceJavaAutoCloudConfiguration
so that the "cloud" keyword is not in the middle. CloudFoundrySolaceAutoConfiguration
feels more natural to me.
Hello,
I'm unsure if this is the right place to ask this question. If not, please let me know the right one.
At my company, we've been using the Cloundfoundry as PaaS, but the Solace service name is not solace-pubsub
, so the library solace-java-cfenv
does not work for me https://github.com/SolaceProducts/solace-spring-boot/tree/master/solace-java-cfenv.
I'm using this dependency in our Spring Boot applications, but it's not able to instantiate the SolaceJavaProperties
and I need to do so on my side because of this issue.
<dependency>
<groupId>com.solace.spring.boot</groupId>
<artifactId>solace-java-spring-boot-starter</artifactId>
</dependency>
Best Regards
The current structure is designed in such a way that the bom is a module like any other modules of this project. This defeats the purpose of testing dependency management internally and separating what is public and what isn't.
The content in its parent (solace-spring-boot-build
)has a number of internal/project specific choices that the bom should not know about. The flatten maven plugin is used to publish a "cleaned" bom. That's a great idea but that doesn't shield you from something that may work here and fail in user's project.
A better arrangement would be to move everything build related from -build
to -parent
and make -parent
inherit from the bom. The Spring Initializr project is a concrete example of such arrangement.
Consider expanding the Spring Boot JMS autoconfig to use the solace.java
credential properties if solace.jms
ones are not specified. This would allow for an app that uses Spring Boot JMS in conjunction with the Spring Cloud Stream Binder or Spring Boot JCSMP to only have to specify credentials once rather than twice like shown below:
solace:
java:
host: ${host:tcp://localhost:55555}
msgVpn: ${msgVpn:default}
clientUsername: ${clientUsername:default}
clientPassword: ${clientPassword:default}
jms:
host: ${host:tcp://localhost:55555}
msgVpn: ${msgVpn:default}
clientUsername: ${clientUsername:default}
clientPassword: ${clientPassword:default}
Hello, I hope you're good!
I would like to know if this project was going to add support for the new PubSub+ java api (https://github.com/SolaceSamples/solace-samples-java)
Thank you!
Use case: I have this setup of Solace where message VPNs are separated based on the business domain. We are designing a Spring Boot application that needs to process the data for different domains using JMS.
Right now solace-spring-boot configuration allows only one message VPN to connect to while the brokers are generally set up with more than one VPNs based on the nature of messages.
Is there any plan to support multiple VPNs using the configuration?
Currently do we have any workaround to setup solace-spring-boot that can subscribe/publish to queues of different VPNs?
The following maven dependency is not needed:
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.19.0</version>
<scope>test</scope>
The only reason for including it is the transient dependency to junit 4.
I have made a pull request: #100
A typical Spring Boot starter (i.e. something that relies on spring-boot-starter
), as the starters of this project, relies on the logging starter which brings the logging infrastructure that Spring Boot uses by default. The current default is logback and users can switch to another logging system as documented in the reference guide.
Currently, the starter brings log4j2. That's breaking the current arrangement. I assume that Solace and the rest of the infrastructure uses slf4j and therefore log4j2 is not a strict requirement. Please consider excluding log4j in the starter (or elsewhere) so that the default arrangement described above is respected.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.