Spring Boot's embedded Tomcat ignores access log configuration - spring

I've enabled the access log as follows:
server.tomcat.basedir=/var/log/my-server/tomcat
server.tomcat.accesslog.directory=.
server.tomcat.accesslog.enabled=true
This usally works in my Spring Boot projects, but not in my current project (Spring Boot 2.6.6), where I'm not using #SpringBootApplication due to some limitations.
I'm currently using the following annotations for my main class:
#SpringBootConfiguration
#ComponentScan
#ServletComponentScan(basePackageClasses = { /* ... */})
#ImportAutoConfiguration({WebMvcAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
ServletWebServerFactoryAutoConfiguration.class})
public class ...
Is there any autoconfiguration I need to import explicitly to configure the embedded tomcat? (server.address as well as server.port gets already respected).

You need to import EmbeddedWebServerFactoryCustomizerAutoConfiguration as well.

Related

Enable Actuator health endpoint without enabling auto config

In my project, I don't want to use #EnableAutoConfiguration. My Application.java has #ComponentScan, #Configuration and #Import annotation.
I have added spring boot actuator dependency in my pom.xml. But, when I try to access http://<>/acutuator/health, I get 404. I believe I need to specify some config class as part of Import annotation. I would need help in figuring out what that config would be.
#EnableAutoConfiguration makes Spring guess configuration based on the classpath, and that's what spring boot all about. If you find that specific auto-configuration classes that you do not want are being applied, you can use the exclude attribute of #EnableAutoConfiguration to disable them. For example:
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})

Spring boot #ConfigurationProperties not loading from external properties file or class path property file

Hi I am trying to use a reusable library that I have created using spring boot(2.0.5) from 2 applications I am able to bind properties from application.properties which is in my classpath to my bean as follows and I see the schemas being set through the setters in my debug in my first spring batch application which is also created with spring boot(2.0.5)
This is the property bean class in my library which holds some service api- this library is just a jar package created with spring boot.
package com.test.lib.config
#ConfigurationProperties("job")
#PropertySources({
#PropertySource(value = "${ext.prop.dir}", ignoreResourceNotFound = true),
#PropertySource(value = "classpath:application.properties", ignoreResourceNotFound = true)
})
public class ServiceProperties {
/**
* Schema for the service
*/
private String schema;
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
}
And the config bean for this library is as follows in the same package.
#Configuration
#EnableConfigurationProperties(ServiceProperties.class)
#ComponentScan("com.test.lib")
public class LibraryModuleConfig {
}
This code works perfectly fine when called from a sprint boot spring batch application which includes this library as a dependency and the corresponding setters are called and I can see the schema set when I add job.schema=testSchema in application.properties
I try to use this same library in an existing spring mvc web application started from a tomcat server with external files directory as launch arguments( This application was not created with spring boot) and added the appropriate context:component-scan to include the beans (java config beans) from the library in the application-context(appn-context.xml). The job.schema property is passed from both application.properties file and even a external file in C drive as given by the ${ext.prop.dir}" in the #propertySources annotation. The schema property in ServiceProperties Bean never gets set and even the setters never get called in the debug. Why will this libray config bean not work in an existing spring mvc application but work with the spring batch application. Both of them add the library as a dependency. I have been at this at a long time and except for the spring property binding the other functionality seem to work.
#EnableConfigurationProperties is a handy annotation that Spring Boot provides. (Spring MVC doesn't provides in default)
For a legacy Spring MVC app (specifically for Spring 3.x), you can use #Value annotation for the properties.
#Value annotation also works in Spring Boot so I guess you can make a change so that it works with older version (Spring 3.x) and newer version just works without changing anything at all.
Hope this helps! Happy Coding :)

Loading application.properties file in a non SpringBoot application

I've a set of microservices built with spring boot and using feign as client. All is working perfectly, but I have a problem with a non SpringBoot application.
In this case I would like to use configuration properties file (application.properties) to configure different client (like Ribbon).
In my configuration bean I've included #ImportAutoConfiguration for all the components, but configuration is not loaded from properties file.
Is there a way to perform this?
Thanks!
import org.springframework.context.annotation.PropertySource;
#RequestMapping("/url")
#Controller
#PropertySource("classpath:config.properties")
public class StudentController{
#Autowired
private Environment env;
//get properties using keys
//env.getProperty("key");
}
and put config.properties file inside src/main/resources

Spring boot auto configuration with dependency and without #ComponentScan

Spring boot provides #ComponentScan to find packages to be scanned.
I am building a library which has #RestControllers inside with package com.mylib.controller. There are other classes as well with stereotype annotations in different packages.
So, if some one is developing SpringBoot Application with com.myapp base package.
He uses my library in his application. He need to mention #ComponentScan("com.mylib") to discover stereotype components of library.
Is there any way to scan components without including library package in #ComponentScan?
As spring-boot-starter-actuator expose its endpoints just with dependency, without defining #ComponentScan. OR any default package which is scanned regardless of application base package.
You could create a Spring Boot Starter in the same style as the Spring Provided Starters. They are essentially a jar'd library with a a spring.factories file pointing to the #Configuration class to load with some other annotations on there to provide overriding/bean back off (#ConditionalOnMissingBean) and generally provide their own #ConfigurationProperties.
Stéphane Nicoll provided an excellent demo of how to build one.
https://github.com/snicoll-demos/hello-service-auto-configuration
It is also documented in the Spring Boot documentation. https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html
The library approach would also work but I see no benefit in not making it a starter. Additionally for any library/starter I'd recommend dropping the #ComponentScan and just defining the beans in a #Configuration. This will work for sterotypes like #RestController etc. will function as normal if you create an #Bean out of it in a configuration.
Spring boot starter are special artifacts designed by Spring and used by Spring.
You can check that in the source code that contains mainly a
spring.provides file :
provides: spring-boot-actuator,micrometer-core
I don't know the exact way to process in the same way as Spring Boot Starter but as probably acceptable workaround, you could define in your jar a #Configuration class that specifies #ComponentScan("com.mylib").
#Configuration
#ComponentScan("com.mylib")
public class MyLibConfig {
//...
}
In this way, clients of the jar need "only" to import the #Configuration class :
#Import(MyLibConfig.class)
#Configuration
public class ClientConfig{
//...
}

How to configure JMX with Spring Boot

I have created a Spring Integration application with Spring Boot. I would like to know how to configure JMX with Spring Boot. I believe by default JMX is configured when using Spring Boot Actuator.
Do I need to configure anything else to be able to export MBeans for Spring Integration?
Most of the example I see have the following line in the applicationContext.xml
<context:mbean-export/>
<context:mbean-server/>
My Application.java class looks like this.
package com.jbhunt.app.consumerappointmentintegration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
#Configuration
#ComponentScan
#EnableAutoConfiguration
#ImportResource("classpath:META-INF/spring/integration/spring-integration-context.xml")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Adding this line to the configuration doesn't seem to export the Spring Integration mbeans
#EnableIntegrationMBeanExport(server = "mbeanServer", defaultDomain="my.company.domain")
I'm referencing this video https://www.youtube.com/watch?v=TetfR7ULnA8
As you understand the Spring Integration JMX is enabled by default, if you just have spring-integration-jmx in the classpath. And, of course, if spring.jmx.enabled = true (default).
You can't overrride that just declaring one more #EnableIntegrationMBeanExport, because it is based on #Import and you just can't override import classes because of (from ConfigurationClassParser):
imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
If imported classes are already there, they aren't overridable.
You have several choices to achieve your requirements:
Disable default Spring Boot JMX - just addind to the application.properties spring.jmx.enabled = false and continue to use #EnableIntegrationMBeanExport
Configure IntegrationMBeanExporter #Bean manually.
Just configure your my.company.domain domain in the application.properties:
spring.jmx.default_domain = my.company.domain
It is quite late to add this; but in addition to the endpoints.jmx.domain I found it useful to change the spring.jmx.default-domain to someting unique per application
This is with multiple instances of Spring Boot 1.4.1 apps running in Tomcat 7

Resources