Spring Boot Java Config Set Session Timeout - spring

How can I configure my (embedded) Tomcat Session Timeout in a Spring Boot Application?
public class SessionListener implements HttpSessionListener{
#Override
public void sessionCreated(HttpSessionEvent se) {
se.getSession().setMaxInactiveInterval(5*60);
}
#Override
public void sessionDestroyed(HttpSessionEvent se) {
}}
I have a SessionListener but I have no idea in which class I have to add this Listener to the Context.

server.session.timeout in the application.properties file is now deprecated. The correct setting is:
server.servlet.session.timeout=60s
Also note that Tomcat will not allow you to set the timeout any less than 60 seconds. For details about that minimum setting see https://github.com/spring-projects/spring-boot/issues/7383.

Spring Boot version 1.0: server.session.timeout=1200
Spring Boot version 2.0: server.servlet.session.timeout=10m
NOTE: If a duration suffix is not specified, seconds will be used.

You should be able to set the server.session.timeout in your application.properties file.
ref: http://docs.spring.io/spring-boot/docs/1.4.x/reference/html/common-application-properties.html
EDIT:
This property has changed in later versions of Spring Boot to server.servlet.session.timeout.
ref: https://docs.spring.io/spring-boot/docs/2.4.x/reference/html/appendix-application-properties.html#server.servlet.session.timeout

Related

How can I override spring.data.mongodb.uri to use mongo TestContainer in Spring boot tests?

I'm trying to implement a bunch of tests using the Mongo TestContainer.
I see that the test container is successfully starting a Mongod instance in docker because I can connect to it using any Mongo Client.
I'm using DynamicPropertySource to override the spring.data.mongodb.uri to one from the TestContainer.
#DynamicPropertySource
static void mongoDbProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.mongodb.uri",
() -> MongoInitializer.MongoContainerSingleton.getInstance().getReplicaSetUrl("testdb"));
}
However, in the logs, I see a timeout because mongoTemplate is still trying to connect to localhost:27017 instead of the port number exposed by the test container.
When I inspect context.getEnvironment() I see that spring.data.mongodb.uri contains the correct uri to the test-container.
I also removed the property from application.properties and tried adding the following to my test.
#TestPropertySource(properties = "spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration")
Nothing worked.
How can I force mongoTemplate to connect to the TestContainer while running tests, while still using the value from application.properties otherwise?
#rieckpil pointed me in the right direction ... Thank you.
I just had to force Spring to use the spring.data.mongodb.uri property by overriding mongoDbFactory() of AbstractMongoClientConfiguration.
#Bean
public MongoDatabaseFactory mongoDbFactory() {
return new SimpleMongoClientDatabaseFactory(
new ConnectionString(Objects.requireNonNull(env.getProperty("spring.data.mongodb.uri")))
);
}
The property set by #DynamicPropertySource in my test then takes priority over the one from application.properties.
getDatebaseName() from AbstractMongoClientConfiguration needs to be implemented, but is ignored because I don't use it in my implementation of mongoDbFactory().

Spring Boot 2.4.3 - Actuator /startup endpoint not found

I have a spring boot app that I upgraded from v2.2.x to now be v2.4.3.
I saw in their documentation that there is a new actuator endpoint of /startup, however it does not exist when I start my app.
There is no special requirement according to their documentation here
I am using spring-boot-admin-starter-client v2.4.3 which provides spring-boot-actuator v2.4.3, and i even have management.endpoint.startup.enabled=true in my application.properties file.
Has anyone else used this version of spring boot and gotten this actuator enpoint to work?
You need to tweak startup configuration:
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(DemoApplication.class);
app.setApplicationStartup(new BufferingApplicationStartup(1000));
app.run(args);
}
}
In application.properties:
management.endpoints.web.exposure.include=startup
If you want to visualize startup events check out this tool I made some months ago https://spring-boot-startup-analyzer.netlify.app/ (look at the configuration instructions as you need to enable CORS on this endpoint)
May be you are using BootstrapApplicationListener which build the application context again but ignores the previous applicationStartup, so it sets the default, this is a bug in spring-cloud-context:3.0.0

How to set enableLoggingRequestDetails='true' in Spring Boot

I'm trying to debug my app today but the spring boot console displays the following message:
enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
Meanwhile, I want to know everything that is going on in the app.
So my question is: How can I enable logging request details in application.properties?
For Spring Boot 2.1 and below use
logging.level.org.springframework.web=DEBUG
spring.http.log-request-details=true
For Spring Boot 2.2 and above spring.http.log-request-details has been deprecated so use
logging.level.org.springframework.web=DEBUG
spring.mvc.log-request-details=true
in your application.properties if you want to see loggingRequestDetails.
From the documentation:
Whether logging of (potentially sensitive) request details at DEBUG
and TRACE level is allowed.
When using webflux and spring boot 2.3.0 the following properties can be set to log request details.
logging.level.org.springframework.web.server.adapter.HttpWebHandlerAdapter=DEBUG
spring.codec.log-request-details=true
for spring boot v2.6.2 you can use this: spring.mvc.log-request-details=true and make sure also you have logging.level.org.springframework.web=DEBUG
spring boot version is 2.2.6.RELEASE.This configuration item below helps me solve the problem.
spring.http.log-request-details=true
If you are using WebFlux turn on the enableLoggingRequestDetails='true' you can by adding:
#Configuration
#EnableWebFlux
public class WebFluxConfig implements WebFluxConfigurer {
#Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.defaultCodecs().enableLoggingRequestDetails(true);
}
}
And setting the config param:
debug:
logging.http-requests: true
logging:
level:
ROOT: INFO
org:
springframework:
web:
server:
adapter:
HttpWebHandlerAdapter: TRACE

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.

Reload property value when external property file changes ,spring boot

I am using spring boot, and I have two external properties files, so that I can easily change its value.
But I hope spring app will reload the changed value when it is updated, just like reading from files. Since property file is easy enough to meet my need, I hope I don' nessarily need a db or file.
I use two different ways to load property value, code sample will like:
#RestController
public class Prop1Controller{
#Value("${prop1}")
private String prop1;
#RequestMapping(value="/prop1",method = RequestMethod.GET)
public String getProp() {
return prop1;
}
}
#RestController
public class Prop2Controller{
#Autowired
private Environment env;
#RequestMapping(value="/prop2/{sysId}",method = RequestMethod.GET)
public String prop2(#PathVariable String sysId) {
return env.getProperty("prop2."+sysId);
}
}
I will boot my application with
-Dspring.config.location=conf/my.properties
I'm afraid you will need to restart Spring context.
I think the only way to achieve your need is to enable spring-cloud. There is a refresh endpoint /refresh which refreshes the context and beans.
I'm not quite sure if you need a spring-cloud-config-server (its a microservice and very easy to build) where your config is stored(Git or svn). Or if its also useable just by the application.properties file in the application.
Here you can find the doc to the refresh scope and spring cloud.
You should be able to use Spring Cloud for that
Add this as a dependency
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter', version: '1.1.2.RELEASE'
And then use #RefreshScope annotation
A Spring #Bean that is marked as #RefreshScope will get special treatment when there is a configuration change. This addresses the problem of stateful beans that only get their configuration injected when they are initialized. For instance if a DataSource has open connections when the database URL is changed via the Environment, we probably want the holders of those connections to be able to complete what they are doing. Then the next time someone borrows a connection from the pool he gets one with the new URL.
Also relevant if you have Spring Actuator
For a Spring Boot Actuator application there are some additional management endpoints:
POST to
/env to update the Environment and rebind #ConfigurationProperties and log levels
/refresh for re-loading the boot strap context and refreshing the #RefreshScope beans
Spring Cloud Doc
(1) Spring Cloud's RestartEndPoint
You may use the RestartEndPoint: Programatically restart Spring Boot application / Refresh Spring Context
RestartEndPoint is an Actuator EndPoint, bundled with spring-cloud-context.
However, RestartEndPoint will not monitor for file changes, you'll have to handle that yourself.
(2) devtools
I don't know if this is for a production application or not. You may hack devtools a little to do what you want.
Take a look at this other answer I wrote for another question: Force enable spring-boot DevTools when running Jar
Devtools monitors for file changes:
Applications that use spring-boot-devtools will automatically restart
whenever files on the classpath change.
Technically, devtools is built to only work within an IDE. With the hack, it also works when launched from a jar. However, I may not do that for a real production application, you decide if it fits your needs.
I know this is a old thread, but it will help someone in future.
You can use a scheduler to periodically refresh properties.
//MyApplication.java
#EnableScheduling
//application.properties
management.endpoint.refresh.enabled = true
//ContextRefreshConfig.java
#Autowired
private RefreshEndpoint refreshEndpoint;
#Scheduled(fixedDelay = 60000, initialDelay = 10000)
public Collection<String> refreshContext() {
final Collection<String> properties = refreshEndpoint.refresh();
LOGGER.log(Level.INFO, "Refreshed Properties {0}", properties);
return properties;
}
//add spring-cloud-starter to the pom file.
Attribues annotated with #Value is refreshed if the bean is annotated with #RefreshScope.
Configurations annotated with #ConfigurationProperties is refreshed without #RefreshScope.
Hope this will help.
You can follow the ContextRefresher.refresh() code implements.
public synchronized Set<String> refresh() {
Map<String, Object> before = extract(
this.context.getEnvironment().getPropertySources());
addConfigFilesToEnvironment();
Set<String> keys = changes(before,
extract(this.context.getEnvironment().getPropertySources())).keySet();
this.context.publishEvent(new EnvironmentChangeEvent(context, keys));
this.scope.refreshAll();
return keys;
}

Resources