Configuring the AJP port on Jetty in a Spring boot application - spring-boot

I am trying to configure the AJP port for the Jetty server in my spring boot application. However, I've seen examples about the Tomcat AJP connector but not for Jetty. Can someone tell me how I should configure the AJP port on Jetty?

Spring boot bundles Jetty 9.3 by default. The AJP feature has been droped in jetty 9. If you really need to use AJP, then you will have to add jetty 8 to your classpath, and write a custom JettyServerCustomizer (http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/context/embedded/jetty/JettyServerCustomizer.html).
I don't think you will find anything in spring documentation regarding this configuration. Once you get to write your customizer, you'll have to read through Jetty documentation to find out how to achieve your AJP configuration.
Jetty has droped AJP in favor of HTTP connector. Unless you have a real use case, I would avise to migrate to HTTP.
I haven't tried the code, but this should work (needs to be wrapped in spring boot code)
return new JettyServerCustomizer() {
#Override
public void customize(Server server) {
s.addConnector(new Ajp13SocketConnector());
}
};
You need jetty-server 8.x and jetty-ajp 8.x in your classpath. With latest 8.x releases, your pom.xml (if you're a maven user) should contain:
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>8.1.19.v20160209</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-ajp</artifactId>
<version>8.1.19.v20160209</version>
</dependency>

Full Sample of The Example Suggested Above For anyone's reference
#Bean
public EmbeddedServletContainerFactory jettyContainer() {
JettyEmbeddedServletContainerFactory factory = new JettyEmbeddedServletContainerFactory();
JettyServerCustomizer customizers = new JettyServerCustomizer() {
#Override
public void customize(Server server) {
// Connector connector = new Ajp13SocketConnector();
// connector.setPort(9009); //if you want a custom port
server.addConnector(new Ajp13SocketConnector());
}
};
factory.addServerCustomizers(customizers);
return factory;
}
Logs
o.e.jetty.server.AbstractConnector: Started
SelectChannelConnector#0.0.0.0:7090 o.e.jetty.server.AbstractConnector
: Started Ajp13SocketConnector#0.0.0.0:9009
o.e.jetty.ajp.Ajp13SocketConnector : AJP13 is not a secure protocol.
Please protect port 9009 .s.b.c.e.j.JettyEmbeddedServletContainer :
Jetty started on port(s) 7090, 9009

Related

How to make Spring Boot 2 Bouncy Castle FIPS compliant?

I am currently trying to make a Spring Boot 2 application to follow all FIPS 140-2 requirements and use TSL in its connections by making use of Bouncy Castle Provider.
So far, I tried looking online what people been doing but it's not straightforward, for example making use of putting jars in your lib folder.
What I tried so far but I don't see how it fits together.
Application main to set Fips Provider
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleFipsProvider());
...
}
Updating java.security (which is now in jdk11/conf/security)
security.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider
And having Bouncy castle jars in classpath of the app
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.58</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bc-fips</artifactId>
<version>1.0.2.1</version>
</dependency>
Configuring bean in Application (but then how to use it?)
#Bean
public Cipher cbcCipher() throws GeneralSecurityException {
Security.addProvider(new BouncyCastleFipsProvider());
return Cipher.getInstance("AES/CBC/PKCS7Padding", "BCFIPS");
}
Interesting pages
Usage of Native Tomcat with OpenSSL to work with Spring Boot but not Bouncy Castle https://medium.com/#crueda/tomcat-native-openssl-in-spring-boot-2-0-a341ad07471d
Bouncy Castle userguide https://downloads.bouncycastle.org/fips-java/BC-FJA-UserGuide-1.0.2.pdf
Are there any application.properties that should be set in the app?
As a note, I added the following and they work fine to read some certificate locally but not using BC FIPS
server.ssl.key-store=classpath:medium.jks
server.ssl.key-store-type=pkcs12
server.ssl.key-store-password=password
server.ssl.key-password=password
server.ssl.key-alias=medium
server.port=8080
Could you please help me see how to attach all these strings together? What am I missing? I suppose how to tell Spring Boot to use BC to its connections in the embedded web server?

Apache Camel-Master/Slave

I've spring boot application which has a set of camel routes. I'm looking for an option to achieve failover in camel routes when one JVM goes down. My goal is to have my app running in one JVM and when that application goes down, another JVM's route should get process my messages.
When I try to add the Clustering, I'm getting an error (Caused by: java.lang.IllegalStateException: CamelCluster service not found) and even I'm not sure whether the way I'm trying my code is correct.
public class RouteCmdLineRunner implements CommandLineRunner {
#Autowired
private Configuration configuration;
#Autowired
private CamelContext camelContext;
#Override
public void run(String... args) {
CamelClusterService atomixClusterService = new AtomixClusterService();
atomixClusterService.setId("camel-node-1");
camelContext.addService(atomixClusterService);
if (configuration != null && configuration.getRoutes() != null) {
configuration.getRoutes().forEach(route -> {
try {
camelContext.addRoutePolicyFactory(ClusteredRoutePolicyFactory.forNamespace("my-ns"));
camelContext.addRoutes(new MyRouteBuilder(route, configuration));
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
}
}
application.yml
camel:
component:
atomix:
cluster:
service:
id: testid-1
enabled: true
order: 1
mode: node
address: localhost:8081
master:
service: AtomixClusterService
camel.clustered.controller.namespace: my-ns
camel.clustered.controller.enabled: true
camel.component.master.service: true
pom.xml
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-master-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-atomix-starter</artifactId>
<version>3.0.0-RC3</version>
</dependency>
<dependency>
<groupId>io.atomix</groupId>
<artifactId>atomix-all</artifactId>
<version>1.0.8</version>
</dependency>
Is Clustering in Camel in the experimental stage? https://camel.apache.org/manual/latest/clustering.html
Camel documentation says it has a master component which does the failover. (https://camel.apache.org/components/latest/master-component.html) but I don't see the complete example for Clustering.
What is the use of a camel clustered controller?
Although there is camel documentation still it is not complete and confusing a lot.
Camel Version: 3.1.0
Spring-boot: 2.2.5.RELEASE
Any pointers would be helpful in achieving Camel clustering. Am I missing anything conceptually?.
For this failover, I don't have the option to install any new server like ZooKeeper/Consul servers.
There is an example on the camel-spring-boot example repo: https://github.com/apache/camel-spring-boot/tree/master/examples/camel-example-spring-boot-clustered-route-controller
Looking at your code I see a number of issues:
you do configure a cluster service programmatically in your run method as well as using spring boot properties
the configuration of master component set AtomixClusterService as service to use but it does not look like you have a bean
so named
One of the two is probably the the reason you are hitting IllegalStateException.
About your questions:
Yes it is still experimental
There is an example at the end of the clustering doc (which is definitively not completed)
the clustered controller is in charge to start/stop routes when the leadership is taken/lost automatically without having you to add any route policy or configuring master component.

Cant change the port for jetty

I am running googleappengine on SpringBoot, I want to change the port number from 8080. In springboot docs, you make the change in application.yml
server:
port: 8090,
or application.properties server.port=8090.
For springboot tomcat, this works, but not for springboot jetty, googleappengine.
Actually the above property should have worked irrespective of the server.
Give a try with below method (Spring boot 2.0).
#Bean
public ConfigurableServletWebServerFactory webServerFactory()
{
JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
factory.setPort(9000);
factory.setContextPath("/myapp");
factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
return factory;
}
Refer configure jetty server spring boot

How to pass additional parameters to MariaDB connect string to fix timezone issue (e.g. useLegacyDatetimeCode)

I'm deploying some spring-boot app to Swisscom AppCloud which uses a MariaDB service. The service gets automatically configured in my app using the CloudFoundry connectors and the connection works fine.
However: since I heavily use ZonedDateTime-Objects in my Java-Code, I also included in the pom.xml...
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-java8</artifactId>
</dependency>
...to properly preserve the ZonedDateTimes in the database.
This works fine on my local MariaDB, when I add...
...?useLegacyDatetimeCode=false
...to the connect string (as described here: https://moelholm.com/2016/11/09/spring-boot-controlling-timezones-with-hibernate/ -> "BONUS TIP: Getting the Hibernate configuration to work with MariaDB / MySQL").
How can I add this flag (and maybe others, too) to the connection to the MariaDB service on Swisscom AppCloud?
If you use Spring on CloudFoundry in conjunction with a MariaDB binding, the datasource is automatically configured by this mechanism: https://docs.cloudfoundry.org/buildpacks/java/spring-service-bindings.html
This is powered by the Spring cloud connectors project, which you can customize to your needs.
I did not test it, but you should be able to set the driver properties as follows:
#Bean
public DataSource dataSource() {
PoolConfig poolConfig = new PoolConfig(5, 30, 3000);
ConnectionConfig connConfig = new ConnectionConfig("useLegacyDatetimeCode=false");
DataSourceConfig dbConfig = new DataSourceConfig(poolConfig, connConfig);
return connectionFactory().dataSource(dbConfig);
}

Spring boot Artemis embedded broker behaviour

Morning all,
I've been struggling lately with the spring-boot-artemis-starter.
My understanding of its spring-boot support was the following:
set spring.artemis.mode=embedded and, like tomcat, spring-boot will instanciate a broker reachable through tcp (server mode). The following command should be successful: nc -zv localhost 61616
set spring.artmis.mode=native and spring-boot will only configure the jms template according to the spring.artemis.* properties (client mode).
The client mode works just fine with a standalone artemis server on my machine.
Unfortunatelly, I could never manage to reach the tcp port in server mode.
I would be grateful if somebody confirms my understanding of the embedded mode.
Thank you for tour help
After some digging I noted that the implementation provided out of the box by the spring-boot-starter-artemis uses org.apache.activemq.artemis.core.remoting.impl.invm.InVMAcceptorFactory acceptor. I'm wondering if that's not the root cause (again I'm by no means an expert).
But it appears that there is a way to customize artemis configuration.
Therefore I tried the following configuration without any luck:
#SpringBootApplication
public class MyBroker {
public static void main(String[] args) throws Exception {
SpringApplication.run(MyBroker.class, args);
}
#Autowired
private ArtemisProperties artemisProperties;
#Bean
public ArtemisConfigurationCustomizer artemisConfigurationCustomizer() {
return configuration -> {
try {
configuration.addAcceptorConfiguration("netty", "tcp://localhost:" + artemisProperties.getPort());
} catch (Exception e) {
throw new RuntimeException("Failed to add netty transport acceptor to artemis instance");
}
};
}
}
You just have to add a Connector and an Acceptor to your Artemis Configuration. With Spring Boot Artemis starter Spring creates a Configuration bean which will be used for EmbeddedJMS configuration. You can see this in ArtemisEmbeddedConfigurationFactory class where an InVMAcceptorFactory will be set for the configuration. You can edit this bean and change Artemis behaviour through custom ArtemisConfigurationCustomizer bean which will be sucked up by Spring autoconfig and be applied to the Configuration.
An example config class for your Spring Boot application:
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptorFactory;
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory;
import org.springframework.boot.autoconfigure.jms.artemis.ArtemisConfigurationCustomizer;
import org.springframework.context.annotation.Configuration;
#Configuration
public class ArtemisConfig implements ArtemisConfigurationCustomizer {
#Override
public void customize(org.apache.activemq.artemis.core.config.Configuration configuration) {
configuration.addConnectorConfiguration("nettyConnector", new TransportConfiguration(NettyConnectorFactory.class.getName()));
configuration.addAcceptorConfiguration(new TransportConfiguration(NettyAcceptorFactory.class.getName()));
}
}
My coworker and I had the exact same problem as the documentation on this link (chapter Artemis Support) says nothing about adding an individual ArtemisConfigurationCustomizer - Which is sad because we realized that without this Customizer our Spring Boot App would start and act as if everything was okay but actually it wouldn't do anything.
We also realized that without the Customizer the application.properties file is not beeing loaded so no matter what host or port you mentioned there it would not count.
After adding the Customizer as stated by the two examples it worked without a problem.
Here some results that we figured out:
It only loaded the application.properties after configuring an ArtemisConfigurationCustomizer
You don't need the broker.xml anymore with an embedded spring boot artemis client
Many examples showing the use of Artemis use a "in-vm" protocol while we just wanted to use the netty tcp protocol so we needed to add it into the configuration
For me the most important parameter was pub-sub-domain as I was using topics and not queues. If you are using topics this parameter needs to be set to true or the JMSListener won't read the messages.
See this page: stackoverflow jmslistener-usage-for-publish-subscribe-topic
When using a #JmsListener it uses a DefaultMessageListenerContainer
which extends JmsDestinationAccessor which by default has the
pubSubDomain set to false. When this property is false it is
operating on a queue. If you want to use topics you have to set this
properties value to true.
In Application.properties:
spring.jms.pub-sub-domain=true
If anyone is interested in the full example I have uploaded it to my github:
https://github.com/CorDharel/SpringBootArtemisServerExample
The embedded mode starts the broker as part of your application. There is no network protocol available with such setup, only InVM calls are allowed. The auto-configuration exposes the necessary pieces you can tune though I am not sure you can actually have a TCP/IP channel with the embedded mode.

Resources