profile
viewpoint

ttddyy/datasource-proxy 395

Provide listener framework for JDBC interactions and query executions via proxy.

r2dbc/r2dbc-proxy 60

R2DBC Proxying Framework

ttddyy/evernote-rest-webapp 26

Stateless MicroService Web Application which provides Restful APIs for Evernote.

ttddyy/datasource-proxy-r2dbc 25

proxy library for R2DBC-SPI

ttddyy/datasource-proxy-examples 20

examples for how to use datasource-proxy

ttddyy/datasource-assert 11

Provides assertion APIs for query executions with assertEquals and assertThat(AssertJ and Hamcrest)

ttddyy/demo 3

demo code

ttddyy/r2dbc-proxy-examples 3

Samples for r2dbc-proxy

ttddyy/datasource-proxy-r2dbc-samples 2

Samples for datasource-proxy-r2dbc

ttddyy/junit5-extension-wait 2

JUnit5 Jupiter extension to delay finishing the test method

delete branch r2dbc/r2dbc-proxy

delete branch : gh-70_custom-subscriber

delete time in 3 days

push eventr2dbc/r2dbc-proxy

Tadaya Tsuyukubo

commit sha d92560f3046ca12983d7b2f72e34e2f18d28e9ea

Extract StopWatch to an independent class

view details

push time in 3 days

push eventr2dbc/r2dbc-proxy

Tadaya Tsuyukubo

commit sha 5a2b4305ecdeef4884e00e71bc452908904b7241

Extract StopWatch to an independent class (cherry picked from commit d92560f3046ca12983d7b2f72e34e2f18d28e9ea)

view details

push time in 3 days

push eventr2dbc/r2dbc-proxy

Tadaya Tsuyukubo

commit sha 0febd39516e11059bba7f05a9c4742d37cfd1122

Introduce "FluxQueryInvocation" Previously, simple Flux with `doFirst()` and `doFinally()` were used to invoke method before/after callbacks. Instead, create `FluxQueryInvocation`, a new FluxOperator` and its subscriber/subscription to perform callback logic. [issue #70]

view details

Tadaya Tsuyukubo

commit sha 8e318e8ebf782fedf8cb48076d65babe6454ae41

Use dedicated operator for method callback Previously, for methods that return publisher, method callback logic is implemented by wrapping the result publisher with new Flux using `doOnSubscribe`, `doFinally`, etc. In this commit, instead of wrap and augment the publisher, creates dedicated operators, `[Mono|Flux]MethodInvocation` and its subscriber/subscription, to handle method callback handling. Also, adds `MonoMethodInvocationConnectionFactoryCreate` to special handle `ConnectionFactory#create` method callbacks. [issue #70]

view details

Tadaya Tsuyukubo

commit sha 4cdbfcc5bd12b4713bfa0fc21d8af937d2d33efb

Use custom subscribers only Previously, custom operators(`[Mono|Flux]MethodInvocation`, etc) were simply delegating the calls to custom subscribers that perform callback logic. In this commit, instead of custom operators, just use custom subscribers and use `Operations#liftPublisher` and `transform()` methods to apply them. [issue #70]

view details

Tadaya Tsuyukubo

commit sha 9f95fe057d95d293429832ba9b905d32941a12bd

Merge branch 'gh-70_custom-subscriber' into main [closes #70]

view details

push time in 3 days

issue closedr2dbc/r2dbc-proxy

Create dedicated subscribers to handle callback logic

Currently, callback logic for methods that return a publisher is implemented by wrapping the result publisher with a new Flux using doOnSubscribe, doFinally, etc., and same for query callback. Since this is a bit fragile implementation, instead, create dedicated custom subscribers that performs callback logic, and apply them to the returned publisher.

closed time in 3 days

ttddyy

push eventr2dbc/r2dbc-proxy

Tadaya Tsuyukubo

commit sha abaca50c04270344274419b335768691b9a4fa43

Introduce "FluxQueryInvocation" Previously, simple Flux with `doFirst()` and `doFinally()` were used to invoke method before/after callbacks. Instead, create `FluxQueryInvocation`, a new FluxOperator` and its subscriber/subscription to perform callback logic. [issue #70]

view details

Tadaya Tsuyukubo

commit sha 80bf30c0bf48634525043cf795a762fdbea874ab

Use dedicated operator for method callback Previously, for methods that return publisher, method callback logic is implemented by wrapping the result publisher with new Flux using `doOnSubscribe`, `doFinally`, etc. In this commit, instead of wrap and augment the publisher, creates dedicated operators, `[Mono|Flux]MethodInvocation` and its subscriber/subscription, to handle method callback handling. Also, adds `MonoMethodInvocationConnectionFactoryCreate` to special handle `ConnectionFactory#create` method callbacks. [issue #70]

view details

Tadaya Tsuyukubo

commit sha 19fd6ad22e0a136b099cc66b666ea8973390f419

Use custom subscribers only Previously, custom operators(`[Mono|Flux]MethodInvocation`, etc) were simply delegating the calls to custom subscribers that perform callback logic. In this commit, instead of custom operators, just use custom subscribers and use `Operations#liftPublisher` and `transform()` methods to apply them. [issue #70]

view details

Tadaya Tsuyukubo

commit sha 2ca64b9ef1e586b01afcc13da491efd72f5c1b22

Merge branch 'gh-70_custom-subscriber' into 0.8.x [closes #70]

view details

push time in 3 days

create barnchttddyy/r2dbc-proxy

branch : 0.8.x

created branch time in 3 days

create barnchr2dbc/r2dbc-proxy

branch : gh-70_custom-subscriber

created branch time in 4 days

issue openedr2dbc/r2dbc-proxy

Create dedicated subscribers to handle callback logic

Currently, callback logic for methods that return a publisher is implemented by wrapping the result publisher with a new Flux using doOnSubscribe, doFinally, etc., and same for query callback. Since this is a bit fragile implementation, instead, create dedicated custom subscribers that performs callback logic, and apply them to the returned publisher.

created time in 4 days

issue commentspring-projects/spring-security

Make "SECURITY_CONTEXT_ATTRIBUTES" key in subscriber context publicly accessible

Yeah, I have a utility class that uses the String key "org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES" to retrieve Authentication from reactor context. This works but since it is bit of internal to the spring security, it would be nice to have public(official) way of getting Authentication(as well as HttpServletRequest and HttpServletResponse) in WebClient filters in servlet environment. I think it is in common needs getting Authentication when writing a custom WebClient filters.

ttddyy

comment created time in 7 days

push eventr2dbc/r2dbc-proxy

Tadaya Tsuyukubo

commit sha 5718b9aa46669fa209d79b41785e80e568e7ca18

Add ProxyConfigHolder Add `ProxyConfigHolder` interface and handling logic to the proxy handler. [closes #69] (cherry picked from commit dfe9e2a218ad52e2f90d6ca280481a22257add2c)

view details

push time in 9 days

issue closedr2dbc/r2dbc-proxy

Provide a mechanism to retrieve "ProxyConfig" from proxied object

Currently, there is no means to retrieve ProxyConfig from proxied objects. Similar to the ConnectionHolder interface which provides a method to extract Connection from proxied objects, introduce ProxyConfigHolder interface and add handling logic to the proxy handler.

closed time in 9 days

ttddyy

push eventr2dbc/r2dbc-proxy

Tadaya Tsuyukubo

commit sha dfe9e2a218ad52e2f90d6ca280481a22257add2c

Add ProxyConfigHolder Add `ProxyConfigHolder` interface and handling logic to the proxy handler. [closes #69]

view details

push time in 9 days

delete branch ttddyy/r2dbc-proxy

delete branch : master

delete time in 9 days

create barnchttddyy/r2dbc-proxy

branch : main

created branch time in 9 days

issue openedr2dbc/r2dbc-proxy

Provide a mechanism to retrieve "ProxyConfig" from proxied object

Currently, there is no means to retrieve ProxyConfig from proxied objects. Similar to the ConnectionHolder interface which provides a method to extract Connection from proxied objects, introduce ProxyConfigHolder interface and add handling logic to the proxy handler.

created time in 9 days

push eventttddyy/r2dbc-proxy-examples

Tadaya Tsuyukubo

commit sha 16d30f6fdbb805607aa459d7e52f1862b0d939cb

Use beforeQuery/afterQuery methods for query execution callback

view details

Tadaya Tsuyukubo

commit sha 5ae0653f4593b52a4701cc1c4532894b6d0db482

Update TracingExecutionListener Adds more endpoints: - `R2dbcSpiController` for using R2DBC SPI - `DatabaseClientController` for using `DatabaseClient` Also, adds unit test for `TracingExecutionListener`.

view details

Tadaya Tsuyukubo

commit sha 102e6158ed1260ef7dcb87f50fe4f232a59944d0

Minor dependency upgrade

view details

push time in 11 days

issue commentspring-projects/spring-framework

Mechanism to access request bound objects in WebClient filter in servlet env

We can aim to make it as easy as possible but we can't make the assumption that it is always needed.

Ok, thanks. At least having mechanism to pass values to nested calls is really helpful. Then, WebClientCustomizer can handle population part in boot application.

ttddyy

comment created time in 12 days

issue commentspring-projects/spring-framework

Support registration of null reference for BeanFactoryPostProcessor

@quaff hm, by quick looking the code, what I can think of are:

  • Original definition is looked up via bean name dataSource, so it won't work when DataSource is registered under different name.
  • Cannot simply retrieve the raw DataSource. It always need to unwrap from TracingDataSource.
  • For DataSource, if connection pool is involved, which usually shaped as DataSource and delegate to actual DataSource, usually what you want to instrument is the outer most DataSource because you want to capture the application behavior not the connection pool behavior. (can be but secondary to the application behavior). I think swapping bean definitions would be difficult to handle such case.
  • It is using GlobalTracer.get() as static retrieval. but you want to allow configuring own tracer bean to use. So, dependency injection would be hard to work on at this low level.
quaff

comment created time in 12 days

issue commentspring-projects/spring-framework

Support registration of null reference for BeanFactoryPostProcessor

I think my solution is simpler and elegant

Haha, yeah, probably. It's subjective and also depends on the requirement of your application. For example, sleuth uses more BPP and open-telemetry maybe use byte code manipulation(I didn't check, simply my guess since I remember I saw ByteBuddy dependency there) for tracing instrumentation. I think one drawback with BFPP impl above is it will lose the original bean definition with original name. So, whether it is acceptable compromise or not is upto the requirement for your app.

Sorry, it has derailed the original issue. Just a bit of side chatting.

quaff

comment created time in 13 days

issue commentspring-projects/spring-framework

Support registration of null reference for BeanFactoryPostProcessor

Hi @quaff

Isn't it more natural to use BeanPostProcessor to decorate those beans?

For example, spring-boot-data-source-decorator wraps DataSource with BPP here.

BTW, if you want to instrument DataSource with tracer, you could use spring-boot-data-source-decorator to wrap DataSource with datasource-proxy or p6spy for Spring Boot application. Or you could use java-jdbc if it is opentracing.

quaff

comment created time in 13 days

push eventr2dbc/r2dbc-proxy

Tadaya Tsuyukubo

commit sha 667d3be9889ecf2134fc2447ed2e930c8fb2e007

Fix "ConnectionFactory#create" after-method callback Wrap the return of `ConnectionFactory#create` with Mono. This fixes after-method callback to be invoked immediately after original `create` method is invoked in case when "usingWhen" is used. [closes #68] (cherry picked from commit 33984e2ed33c5ca606b02587c3cb92d0c92db5ef)

view details

push time in 13 days

issue closedr2dbc/r2dbc-proxy

Make "afterMethod" callback work correctly for "ConnectionFactory#create" with "usingWhen"

When [Mono|Flux]#usingWhen is used for ConnectionFactory#create(), afterMethod callback is performed AFTER Connection::close(from async-cleanup).

Flux.usingWhen(connectionFactory.create(), connection -> {
    // perform db operation
}, Connection::close, (c, err) -> c.close(), Connection::close);

This is because usingWhen method defers the completion of "resource supplier"(ConnectionFactory#create) until "async-cleanup"(Connection#close) to be finished.

There are two ways in r2dbc-proxy to make this work:

  • Wrap the proxied result(Flux) to Mono. When first element is emitted, the Mono makes cancel to the wrapped Flux which triggers doFinally on the Flux before "async-cleanup".

  • Use doOnNext to trigger afterMethod callback. Instead of using doFinally, special handle the ConnectionFactory#create to use doOnNext() to trigger the afterMethod callback. As soon as an element is emitted, doOnNext() is called before "async-cleanup".

If client side need to make it work for now, the quick workaround is:

Wrap the ConnectionFactory#create with Mono#from

return Flux.usingWhen(Mono.from(this.connectionFactory.create()), connection -> {
  // logic to access DB
}, Connection::close, (c, err) -> c.close(), Connection::close);

For DatabaseClient in spring, the logic to acquire a connection already wraps the ConnectionFactory#create with Mono; so, DatabaseClient works without any changes.

private static Mono<Connection> fetchConnection(ConnectionFactory connectionFactory) {
  return Mono.from(connectionFactory.create());
}

closed time in 13 days

ttddyy

push eventr2dbc/r2dbc-proxy

Tadaya Tsuyukubo

commit sha 33984e2ed33c5ca606b02587c3cb92d0c92db5ef

Fix "ConnectionFactory#create" after-method callback Wrap the return of `ConnectionFactory#create` with Mono. This fixes after-method callback to be invoked immediately after original `create` method is invoked in case when "usingWhen" is used. [closes #68]

view details

push time in 13 days

issue commentspring-projects/spring-framework

Mechanism to access request bound objects in WebClient filter in servlet env

add an option to have ClientRequest attributes be saved under some well known key in the Reactor context.

This sounds a nice solution.

It may also be good to auto attach servlet request, etc to the reactor context if in servlet environment; So that, ExchangeFilterFunction can have consistent way to retrieve servlet request and values associated to the attributes. This gives benefit to library writers since everything concludes in ExchangeFilterFunction, maybe in combination with servlet Filter to populates values to request attributes, instead of interleaving WebClient.Builder or WebClient#attributes at WebClient build time.

ttddyy

comment created time in 14 days

issue commentspring-projects/spring-framework

Mechanism to access request bound objects in WebClient filter in servlet env

If WebClient.Builder could setup its subscriber context(defaultContext method below), maybe this would work.

FooContext.set("main-thread");  // setting to threadlocal

// a filter uses "foo" from subscriber context
ExchangeFilterFunction filter = (request, next) ->
    Mono.subscriberContext()
        .map(context -> (String) context.get("foo"))
        .map(foo -> ClientRequest.from(request).header("foo", foo).build())
        .flatMap(next::exchange);


WebClient webClient = WebClient.builder()
        .filter(filter)
        // populate subscriber context
        .defaultContext(context -> context.hasKey("foo") ? context : context.put("foo", FooContext.get()))
        .build();

webClient.get()
        .uri("http://foo.com")
        .retrieve()
        .bodyToMono(String.class)
        .flatMap(body ->
                webClient.get()
                        .uri("http://bar.com")
                        .retrieve()
                        .bodyToMono(String.class)
        )
        .subscribeOn(Schedulers.boundedElastic())  // on different thread...
        ....
;

// both calls will have header "foo=main-thread"

When nested WebClient is called, the context key "foo" has already populated by outer WebClient, which used the original caller's thread.

Not sure it is even possible, but an idea.

ttddyy

comment created time in 15 days

issue openedr2dbc/r2dbc-proxy

Make "afterMethod" callback work correctly for "ConnectionFactory#create" with "usingWhen"

When [Mono|Flux]#usingWhen is used for ConnectionFactory#create(), afterMethod callback is performed AFTER Connection::close(from async-cleanup).

Flux.usingWhen(connectionFactory.create(), connection -> {
    // perform db operation
}, Connection::close, (c, err) -> c.close(), Connection::close);

This is because usingWhen method defers the completion of "resource supplier"(ConnectionFactory#create) until "async-cleanup"(Connection#close) to be finished.

There are two ways in r2dbc-proxy to make this work:

  • Wrap the proxied result(Flux) to Mono. When first element is emitted, the Mono makes cancel to the wrapped Flux which triggers doFinally on the Flux before "async-cleanup".

  • Use doOnNext to trigger afterMethod callback. Instead of using doFinally, special handle the ConnectionFactory#create to use doOnNext() to trigger the afterMethod callback. As soon as an element is emitted, doOnNext() is called before "async-cleanup".

If client side need to make it work for now, the quick workaround is:

Wrap the ConnectionFactory#create with Mono#from

return Flux.usingWhen(Mono.from(this.connectionFactory.create()), connection -> {
  // logic to access DB
}, Connection::close, (c, err) -> c.close(), Connection::close);

For DatabaseClient in spring, the logic to acquire a connection already wraps the ConnectionFactory#create with Mono; so, DatabaseClient works without any changes.

private static Mono<Connection> fetchConnection(ConnectionFactory connectionFactory) {
  return Mono.from(connectionFactory.create());
}

created time in 17 days

issue commentspring-projects/spring-framework

Mechanism to access request bound objects in WebClient filter in servlet env

@rstoyanchev Oh, I wasn't aware of attributes method. Thanks. Certainly it would be nice to mention ThreadLocal in documentation for attribute method usage.

I have simulated couple of our usecases trying with attributes in servlet environment with WebClient. This serves most of the cases since I can assign values to attributes from Threadlocal at the time when request is made and on the thread that is making a request.

However, I found one case hard to do with attributes, which is nesting remote calls. For example, make a first remote call, then based on the response, create another remote call.

Sample code:

ExchangeFilterFunction filter = (request, next) -> {
  log.info("filter map=" + request.attributes());
  return next.exchange(request);
};

WebClient webClient = WebClient.builder().filter(filter).defaultRequest(spec -> {
  spec.attribute("bar", "BAR");
  spec.attribute("tid", Thread.currentThread().getId());
  spec.attribute("tname", Thread.currentThread().getName());
}).build();

webClient.get().uri("http://service1.com")  // first call
    .attribute("foo", "FOO")
    .retrieve()
    .bodyToMono(String.class)
    .flatMap(str -> {
      return webClient.get().uri("http://service2.com")  // second call
          .retrieve()
          .bodyToMono(String.class);
    })
    .subscribeOn(Schedulers.boundedElastic())  // on different thread...
    .block();

When making the first call, attributes tid and tname are main thread, but for the second call, the thread is on elastic thread; so cannot retrieve thread local values that are bound to the caller.

In the real environment, these two calls are service-to-service calls and when I call another service, I need to propagate some values stored in caller's thread local. (very much similar to ServletBearerExchangeFilterFunction in Spring Security)

Workaround can be, when constructing the second call, explicitly add attribute method and pass a value that the filter is looking for. However, it is invasive to application code and would like to handle it in filter or construction of webclient in library.

Currently, I use subscriber context approach as mentioned in the description. (reusing SecurityReactorContextSubscriberRegistrar from Spring Security)

Also, interesting thing is that the ServletOAuth2AuthorizedClientExchangeFilterFunction (pointed in your comment) uses attributes but also it is getting attribute values(request, response, and auth) from subscriber context which is populated by the lifter hook (SecurityReactorContextSubscriberRegistrar).

So, attributes works for single remote call cases, but when multiple calls on different threads are involved, I think above mentioned Hook approach may be in need.

ttddyy

comment created time in 17 days

pull request commentspring-projects/spring-framework

Efficiency of beanfactory postprocessors execution

I believe priority ordered BFPPs need to be applied first, THEN rest of the BFPP can be instantiated.

huangfusuper

comment created time in 20 days

issue commentspring-projects/spring-boot

Provide diagnostic information about the ordering of auto-configuration classes

For those who want to have auto configuration order logged: I wrote this class as a temporal workaround to write out "Auto configuration order report" to the log. This class reflectively accesses auto configuration sorter and write the report upon receiving AutoConfigurationImportEvent.

code:

/**
 * Write the processing order of auto configuration classes to the log.
 * <p>
 * This implementation reflectively invokes {@code AutoConfigurationSorter} to sort auto
 * configuration classes since Spring Boot does not expose the sorting infrastructure for
 * auto configuration classes.
 * <p>
 * Note: This class doesn't work with {@code ApplicationContextRunner}. This is because
 * {@code ApplicationContextRunner} does not trigger
 * {@link AutoConfigurationImportListener} event and relies on the directly
 * populating(recording) {@link ConditionEvaluationReport} via
 * {@link SpringBootCondition}. The configuration order is sorted by
 * {@code AutoConfigurations} when new configurations are added to the runner. One
 * possible solution is to use {@code ApplicationContextRunner#with} method to return a
 * proxy. At the time of running the runner, it can introspect all configurations, which
 * has ordered, and report the order of auto configuration classes.
 * <p>
 * https://github.com/spring-projects/spring-boot/issues/20732
 *
 * @author Tadaya Tsuyukubo
 */
// Inherit the logging category from Spring Boot. For example, with "--debug" option,
// "LoggingApplicationListener" sets the log level to "debug" for Spring Boot categories.
// Then, this logger will automatically inherit the same level.
@Slf4j(topic = "org.springframework.boot.mylib")
public class AutoConfigurationOrderLoggingListener
		implements BeanFactoryAware, ResourceLoaderAware, AutoConfigurationImportListener {

	private static final String SORTER_CLASS = "org.springframework.boot.autoconfigure.AutoConfigurationSorter";

	private ConfigurableListableBeanFactory beanFactory;

	private ResourceLoader resourceLoader;

	@Override
	public void onAutoConfigurationImportEvent(AutoConfigurationImportEvent event) {
//		if (!log.isDebugEnabled()) {
//			return; // only run when debug is on
//		}

		List<String> configs = event.getCandidateConfigurations();
		List<String> sorted;
		try {
			sorted = sort(configs);
		}
		catch (Exception ex) {
			log.error("Failed to sort auto configuration classes", ex);
			return; // do not proceed
		}

		// If we want to follow how "ConditionEvaluationReport" is logged, log them at
		// "ContextRefreshedEvent" and "ApplicationFailedEvent" with implementing
		// "GenericApplicationListener" (see "ConditionEvaluationReportLoggingListener").
		// Then, register to "spring.factories" as "ApplicationListener".
		logAutoConfigurationOrder(sorted);
	}

	private void logAutoConfigurationOrder(List<String> configs) {
		StringBuilder sb = getLogMessage(configs, "AUTO CONFIGURATION ORDER REPORT");
		log.debug(sb.toString());
	}

	private StringBuilder getLogMessage(List<String> configs, String title) {
		StringBuilder message = new StringBuilder();
		message.append(String.format("%n%n%n"));
		StringBuilder separator = new StringBuilder();
		for (int i = 0; i < title.length(); i++) {
			separator.append("=");
		}
		message.append(String.format("%s%n", separator));
		message.append(String.format("%s%n", title));
		message.append(String.format("%s%n%n%n", separator));
		for (int i = 0; i < configs.size(); i++) {
			message.append(String.format("%3d - %s%n", i + 1, configs.get(i)));
		}
		message.append(String.format("%n%n"));
		return message;
	}

	// Equivalent to
	// "org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup.sortAutoConfigurations"
	@SuppressWarnings("unchecked")
	private List<String> sort(List<String> configs) throws Exception {

		Class<?> clazz = ClassUtils.resolveClassName(SORTER_CLASS,
				AutoConfigurationOrderLoggingListener.class.getClassLoader());
		Method method = ReflectionUtils.findMethod(clazz, "getInPriorityOrder", Collection.class);
		ReflectionUtils.makeAccessible(method);

		Constructor<?> constructor = ReflectionUtils.accessibleConstructor(clazz, MetadataReaderFactory.class,
				AutoConfigurationMetadata.class);
		Object[] args = new Object[] { getMetadataReaderFactory(), getAutoConfigurationMetadata() };

		Object sorter = BeanUtils.instantiateClass(constructor, args);

		List<String> sorted = (List<String>) ReflectionUtils.invokeMethod(method, sorter, configs);
		return sorted;
	}

	// Equivalent to
	// "org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup.getMetadataReaderFactory"
	private MetadataReaderFactory getMetadataReaderFactory() {
		String beanName = "org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory";
		try {
			return this.beanFactory.getBean(beanName, MetadataReaderFactory.class);
		}
		catch (NoSuchBeanDefinitionException ex) {
			return new CachingMetadataReaderFactory(this.resourceLoader);
		}
	}

	// Equivalent to
	// "org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup.getAutoConfigurationMetadata"
	private AutoConfigurationMetadata getAutoConfigurationMetadata() {
		String loaderClass = "org.springframework.boot.autoconfigure.AutoConfigurationMetadataLoader";
		Class<?> clazz = ClassUtils.resolveClassName(loaderClass,
				AutoConfigurationOrderLoggingListener.class.getClassLoader());
		Method method = ReflectionUtils.findMethod(clazz, "loadMetadata", ClassLoader.class);
		ReflectionUtils.makeAccessible(method);
		AutoConfigurationMetadata metadata = (AutoConfigurationMetadata) ReflectionUtils.invokeMethod(method, null,
				AutoConfigurationOrderLoggingListener.class.getClassLoader());
		return metadata;
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory);
		this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
	}

	@Override
	public void setResourceLoader(ResourceLoader resourceLoader) {
		this.resourceLoader = resourceLoader;
	}

}

spring.factories:

org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
com.example.AutoConfigurationOrderLoggingListener
ttddyy

comment created time in 24 days

issue commentspring-projects/spring-boot

Investigate shutdown delay option

We have an operational scenario that directly open a shell on the pod and restart the application. This allows faster restart of the app since it doesn't involve k8s pod lifecycle.

In such case, k8s does not know the application is restarting and it still send traffic to the pod during shutdown. So, in our graceful shutdown logic(in addition to the one from boot 2.3), we put a sleep for the duration of readiness check frequency, to make sure k8s readiness check picks up that the app is about to restarting and stop routing the traffic before actual shutdown happens.

If Spring Boot provides sleep(delay) on its graceful shutdown logic, I can remove our sleep logic from our library, which is great.

philwebb

comment created time in 24 days

issue openedspring-projects/spring-security

Make "SECURITY_CONTEXT_ATTRIBUTES" key in subscriber context publicly accessible

We use WebClient in servlet environment. Some of our ExchangeFilterFunction requires current authentication object as well as values associated to the http request. Previously, with RestTemplate, we used ThreadLocal to hold and retrieve request bounded values.(RequestContextHolder, SecurityContextHolder, etc.)

With WebClient, Spring Security's SecurityReactorContextSubscriber in SecurityReactorContextConfiguration exposes auth, servlet request, and servlet response in a Map(called ContextAttributes) to the subscriber context.

In our custom filter functions, we leverage this context-attributes-map to retrieve auth and request bounded values similar to what ServletBearerExchangeFilterFunction does.

Currently, to access this context-attributes-map, the key SECURITY_CONTEXT_ATTRIBUTES is defined as package private in SecurityReactorContextConfiguration.

static final String SECURITY_CONTEXT_ATTRIBUTES = "org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES";

Even within Spring Security, ServletBearerExchangeFilterFunction(oauth2-resource-server module) and ServletOAuth2AuthorizedClientExchangeFilterFunction(oauth2-client module) which define same String constant key in order to access this context-attributes-map. This is probably due to the SECURITY_CONTEXT_ATTRIBUTES constant is defined in SecurityReactorContextConfiguration(config module) which is a downstream module(and class is package private).

So, to allow context-attributes-map being used not only by oauth2-[resource-server|client] modules, but also user library/application, can this SECURITY_CONTEXT_ATTRIBUTES constant (and maybe mechanism around) be exposed to somewhere in upstream module public class? Also, the context-attributes-map can be an independent class instead of generic Map to enhance accessibility of stored objects.

Ideally, I think this infrastructure(subscriber, lifter, context-attributes-map) is available in Spring Framework; then, Spring Security adds a logic to populate SecurityContext on it. (https://github.com/spring-projects/spring-framework/issues/25710)

created time in 24 days

issue openedspring-projects/spring-framework

Mechanism to access request bound objects in WebClient filter in servlet env

In servlet environment, when migrating RestTemplate to WebClient, one of the challenges people face is to access http request bound objects within WebClient filters(ExchangeFilterFunction). I think this is an area currently lacking a support.

For example, SecurityContext, Locale/LocaleContext(LocaleContextHolder), HttpServletRequest(RequestContextHolder) and any values associated to the request(ThreadLocal) cannot easily be retrieved in ExchangeFilterFunction.

I think common solution for this is to use Hooks to populate the values to subscriber's context.

For example, in Spring Security, here defines and registers a hook that populates SecurityContext. Since this mechanism also populates HttpServletRequest and HttpServletResponse, I leverage it in my exchange filter functions to retrieve request bound values. I also have similar logic for MDC and LocaleContext.

I think this mechanism should be supported in Spring Framework itself; so that, all downstream libraries and application can leverage it.

For implementation perspective, for example, define a class ReactorContextAttribute which is a map kept in thread local. Then, framework guarantees to populate this map in subscriber's context. So that, users or downstream libraries can simply populate this map in request thread, then retrieves values from the map in subscriber context. In addition, FrameworkServlet/DispatcherServlet resolved value/context, such as LocaleContext, can be placed in this map to make them accessible in exchange filter functions.

If such mechanism exists, for example, Spring Security can simply add a logic to populate SecurityContext.

I think this is a big missing piece to use WebClient in servlet environment along with supporting MDC.

created time in 24 days

issue openedspring-projects/spring-framework

Inconsistent log level in @Bean javadoc and ConfigurationClassEnhancer

@Bean javadoc states when BFPP is defined with non-static method, it writes a WARN-level log message.

This works out in BFPP cases, as they are not typically referenced by other @Bean methods. As a reminder, a WARN-level log message will be issued for any non-static @Bean methods having a return type assignable to BeanFactoryPostProcessor

The commit 9a43d2ec208d2e8cd0866431acf26af3529f8677 (SPR-16946, #21485) updated the logging level in ConfigurationClassEnhancer and this message shows up as INFO log.

if (logger.isInfoEnabled() &&
    BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
  logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
          "assignable to Spring's BeanFactoryPostProcessor interface. This will " +
          "result in a failure to process annotations such as @Autowired, " +
          "@Resource and @PostConstruct within the method's declaring " +
          "@Configuration class. Add the 'static' modifier to this method to avoid " +
          "these container lifecycle issues; see @Bean javadoc for complete details.",
      beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
}

So, either javadoc or log level need to be updated to match actual description and behavior.

created time in a month

issue openedspring-projects/spring-boot

Different bean resolution in @ConditionalOn*Bean vs autowiring

One of the application team reported an issue and I found this slightly unintuitive behavior between condition evaluation of @ConditionalOn*Bean and spring's autowiring resolution for method argument.

Sample Code:

public class AnotherApplication {
	public static void main(String[] args) {
		SpringApplication.run(Config.class, "--debug");
	}

	@SpringBootConfiguration(proxyBeanMethods = false)
	static class Config {

		@Bean
		Parent foo() {
			return new Child("FOO");
		}

		@Bean
		Child bar() {
			return new Child("BAR");
		}

//		@Bean
//		Parent baz() {
//			return new Child("BAZ");
//		}

		@Bean
		@ConditionalOnSingleCandidate(Child.class)	// <<<--
		InitializingBean init(Child child) {		// <<<--
			return () -> {
				System.out.println("initialized");
			};
		}

	}

	static class Parent {
		String name;

		public Parent(String name) {
			this.name = name;
		}
	}

	static class Child extends Parent {
		public Child(String name) {
			super(name);
		}
	}
}

Condition evaluation report:

Positive matches:
-----------------

   AnotherApplication.Config#init matched:
      - @ConditionalOnSingleCandidate (types: com.example.AnotherApplication$Child; SearchStrategy: all) found a primary bean from beans 'bar' (OnBeanCondition)

Failure:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method init in com.example.AnotherApplication$Config required a single bean, but 2 were found:
	- foo: defined by method 'foo' in com.example.AnotherApplication$Config
	- bar: defined by method 'bar' in com.example.AnotherApplication$Config

Analysis

While performing OnBeanCondition(@ConditionalOnSingleCandidate), it compares the target type(Child) against factory-method-return-type of each @Bean - Parent for bean foo and Child for bar. Therefore, Child matches to bar bean and satisfies the condition.

The details of this process is, in OnBeanCondition, it calls beanFactory.getBeanNamesForType to collect bean names for the specified type(Child). In that, it calls AbstractBeanFactory#getSingleton. At this time, spring did not create raw beans yet, thus, the beanInstance becomes null. Then, it goes to check the bean definition's factoryMethodReturnType against specified condition type Child.

On the other hand, when spring performs autowiring for method arguments, it also calls beanFactory.getBeanNamesForType. At this time, raw beans are available, and it finds the actual bean instances. Then, it proceeds to perform instanceof check against the method argument type Child. This instanceof matches to both foo(Parent) and bar(Child) beans. Therefore, it detects two beans and fails to resolve which one to apply for the method argument.


There is another not intuitive behavior.

In following situation, it will not match the condition because the return type of foo is Parent.

@Configuration(proxyBeanMethods = false)
static class Config {

  @Bean
  Parent foo() {
    return new Child("FOO");
  }

  @Bean
  @ConditionalOnBean(Child.class)
  InitializingBean init(Child child) {
    ...
  }

}
Negative matches:
-----------------

   AnotherApplication.Config#init:
      Did not match:
         - @ConditionalOnBean (types: com.example.AnotherApplication$Child; SearchStrategy: all) did not find any beans of type com.example.AnotherApplication$Child (OnBeanCondition)

However, once I add Child bar() bean, suddenly the condition matches but autoconfiguration for Child fails with finding two beans - foo and bar.

@Configuration(proxyBeanMethods = false)
static class Config {

  @Bean
  Parent foo() {
    return new Child("FOO");
  }

  @Bean
  Child bar() {
    return new Child("BAR");
  }

  @Bean
  @ConditionalOnBean(Child.class)
  InitializingBean init(Child child) {
    ...
  }

}
Positive matches:
-----------------

   AnotherApplication.Config#init matched:
      - @ConditionalOnBean (types: com.example.AnotherApplication$Child; SearchStrategy: all) found bean 'bar' (OnBeanCondition)
***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method init in com.example.AnotherApplication$Config required a single bean, but 2 were found:
	- foo: defined by method 'foo' in com.example.AnotherApplication$Config
	- bar: defined by method 'bar' in com.example.AnotherApplication$Config

This suddenly matching multiple beans issue has reported in our application and I found this behavior.

I understand this is possibly working as designed.
The difference is due to the behavior of beanfactory.getBeanNamesForType which changes slightly different based on the stage this method is called. And also due to that bean instances cannot be checked while processing conditions.

It might be a corner case, but may be good to document such behavior on @ConditonalOn*Bean annotations.

created time in 2 months

pull request commentpgjdbc/r2dbc-postgresql

added parameter bind logging

FYI, If you want to log bindings and query all together(also connection id), r2dbc-proxy provides such capability. Here is sample log. (It is multilined for display purpose but actual logging is single line, and configurable to own format)

62mkv

comment created time in 2 months

push eventttddyy/spring-boot

bono007

commit sha ac651442fa82817a13654208328c3e45188fa305

Add support for selecting the Redis client to use See gh-22569

view details

Stephane Nicoll

commit sha 589669d0cc49f05381cdf947e69804aa4d720a0d

Polish "Add support for selecting the Redis client to use" See gh-22569

view details

Stephane Nicoll

commit sha 0bc5b20d561b44c6d89ac2f2e4826e9db985f3a0

Merge pull request #22569 from bono007 * pr/22569: Polish "Add support for selecting the Redis client to use" Add support for selecting the Redis client to use Closes gh-22569

view details

Danilo Piazzalunga

commit sha 5352ec1cbaa36b14da031da1b5a42f86d79aa370

Support configuration of entityId for a SAML Relying Party See gh-22258

view details

Stephane Nicoll

commit sha 621f0264990d36f30cee6149eb2e6a1f43b302ab

Polish "Support configuration of entityId for a SAML Relying Party" See gh-22258

view details

Stephane Nicoll

commit sha b476bf82d8877e3b0b56f48f7ce7c48b94d57fb2

Merge pull request #22258 from danilopiazza * pr/22258: Polish "Support configuration of entityId for a SAML Relying Party" Support configuration of entityId for a SAML Relying Party Closes gh-22258

view details

Andy Wilkinson

commit sha 2238b0d797be0fe55710f168cdde47cf2eca0dea

Try to make FileSystemWatcherTests.waitsForQuietPeriod() more robust Previously, waitsForQuietPeriod would iterate 10 times, touching a new file and then sleeping for 100ms at it did so. With a quiet period of 200ms, this was intended to result in a single change set containing 10 files. However, the test would fail occasionally as multiple change sets were detected. The test is multi-threaded and is, therefore, at the mercy of the scheduler. If the thread that is iterating and touching the files takes over 200ms to be scheduled – exceeding the watcher's quiet period – the watcher may detect a change set while the changes are still being made. Eliminating this possibilty would require the test to participate in the watcher's synchronization, which would require some changes to its implementation. Instead, this commit aims to avoid the problem by sleeping for 1/10 of the time (10ms) and expecting a single change set of 100 files. The hope is that the much shorter sleep time will result in the file touching thread being scheduled well within the 200ms quiet period. Closes gh-22732

view details

Andy Wilkinson

commit sha 94644f381466d3e06cb7ea4cf2175f593bab201d

Merge branch '2.2.x' into 2.3.x Closes gh-22737

view details

Andy Wilkinson

commit sha 7df49187fa4f5f469bb8785caceebadacbec53ed

Merge branch '2.3.x' Closes gh-22738

view details

ayudovin

commit sha ae152b176ba0050aecfea724750f060eaf473f6b

Add test slice for Spring Data Cassandra See gh-17490

view details

Stephane Nicoll

commit sha 313b2bef6fa396c16635914e1021f0af3418ee2c

Polish "Add test slice for Spring Data Cassandra" See gh-17490

view details

Stephane Nicoll

commit sha b51e612c39c68b5940fe80053f9469a047c13bed

Merge pull request #17490 from ayudovin * pr/17490: Polish "Add test slice for Spring Data Cassandra" Add test slice for Spring Data Cassandra Closes gh-17490

view details

Johnny Lim

commit sha 1017774ed59c9835a079475df62f8b3edde1d0e9

Polish See gh-22740

view details

Stephane Nicoll

commit sha cccf9c24e21e8788cbed54334e6db383df599134

Merge pull request #22740 from izeye * pr/22740: Polish Closes gh-22740

view details

Stephane Nicoll

commit sha 516582f6d323dd39648dd9bda5b8c600a15c30a5

Merge branch '2.3.x' Closes gh-22744

view details

Andy Wilkinson

commit sha 71ffb44a3c6d2043cc491bb576518116015c5744

Remove WebClient's in-memory buffer size limit for endpoint tests Previously, the endpoints' responses could occasionally exceed WebClient's in-memory buffer limt, for example if the threads endpoint was reporting a large number of threads or the threads had large stacks. This commit disables WebClient's in-memory buffer size limit so that the tests passing is not dependent on the size of the endpoints' responses. Closes gh-22743

view details

Andy Wilkinson

commit sha c40835eba0935d5ed11df31cf6bbee6313f8e396

Merge branch '2.2.x' into 2.3.x Closes gh-22746

view details

Andy Wilkinson

commit sha 0e83b2f4c4fee7b3843c2b175e7a3402894e3b92

Merge branch '2.3.x' Closes gh-22747

view details

Andy Wilkinson

commit sha bfe250e5d33aafe384604f01f7823ce8265e6a84

Clarify docs on schema and data SQL scripts with Flyway and Liquibase Closes gh-20920

view details

Andy Wilkinson

commit sha a160755da51b56be981d5d1f39ab70372092b766

Merge branch '2.2.x' into 2.3.x Closes gh-22748

view details

push time in 2 months

delete branch ttddyy/spring-framework

delete branch : 24634_order-detected-ex-translator

delete time in 2 months

delete branch ttddyy/spring-framework

delete branch : remove-nullable

delete time in 2 months

create barnchttddyy/spring-framework

branch : remove-nullable

created branch time in 2 months

PR opened spring-projects/spring-framework

Remove @Nullable from CookieLocaleResolver#determineDefaultLocale()

By definition, this method should not return null.

+0 -1

0 comment

1 changed file

pr created time in 2 months

issue commentr2dbc/r2dbc-spi

Add a method to unwrap to the specified class from nested wrapped object

The usecase for me is more on testing side at the moment. When ConnectionFactory is created automatic(dynamic) fashion (e.g: spring-boot auto configuration), caller may not know how many times it is wrapped. So, need to introspect(unwrap) each of the object until it finds what it is looking for.

This, in turn, same for users who need to use implementation specific feature(one that is not available in SPI). The logic may not know how the object is constructed, so need to loop through the unwrapping.

The proposed API would not matter unwrapping type is either same as wrapping type or can be even different(not sure it's realistic or not though).

ttddyy

comment created time in 2 months

issue openedr2dbc/r2dbc-spi

Add a method to unwrap to the specified class from nested wrapped object

Currently Wrapped#unwrap retrieves the holding original object on the instance. If an object is wrapped multiple times, then the caller needs to iterate through the target to find the one that is looking for to be unwrapped.

For example, if an object ConnectionFactory is wrapped as proxy -> pool -> H2 ConnectionFactory, caller needs to unwrap twice to get the original H2 connection-factory.

Similar to Wrapper#unwrap(Class) in JDBC, it is helpful for users to directly return unwrapping target object if it is available from wrapped object, or returns null.

This can be implemented in default method on the Wrapped interface.(Or static method) So that, each implementation does not need to handle the call.

Here is a sample implementation with default method to find the first (outer most) wrapped object that matches to the given class.

@Nullable
@SuppressWarnings("unchecked")
default <E> E unwrapTo(Class<E> targetClass) {
    Assert.requireNonNull(targetClass, "targetClass must not be null");
    Object target = this;
    while (true) {
        if (targetClass.isInstance(target)) {
            return (E) target;
        }
        if (!(target instanceof Wrapped)) {
            return null;
        }
        target = ((Wrapped<?>) target).unwrap();
    }
}

We can have more generic one with Predicate:

@Nullable
default <E> E unwrapTo(Class<E> targetClass) {
    return unwrapTo(targetClass::isInstance);
}

@Nullable
@SuppressWarnings("unchecked")
default <E> E unwrapTo(Predicate<Object> predicate) {
    ....
}

For boolean check (if we want), we could reuse above like:

default boolean isWrapping(Class<?> targetClass) {
    return unwrapTo(targetClass) != null;
}

created time in 2 months

push eventttddyy/spring-boot

Tadaya Tsuyukubo

commit sha 630cbae7d7d6b7d9a5d672a793e1a1f807cf0b36

Document properties to enable probe health indicators Document property names to enable probe(readiness/liveness) health indicators. See gh-22631

view details

Brian Clozel

commit sha 35093aacf4f45aa9eb29d2afb536d2103442ed6a

Polish "Document properties to enable probe health indicators" See gh-22631

view details

Brian Clozel

commit sha 4aa010c874beb53df58b018aeea71e5b00829c25

Merge pull request #22631 from ttddyy * gh-22631: Polish "Document properties to enable probe health indicators" Document properties to enable probe health indicators Closes gh-22631

view details

Brian Clozel

commit sha e6957ec8c4a8ffc5c8945cc12714674307363e02

Merge branch '2.3.x' Closes gh-22697

view details

Brian Clozel

commit sha 8dedeb4c6a66bf518a455bf1331ebdb9a94bda19

Fix missing liveness and readiness indicators Prior to this commit, the livenessState and readinessState health indicators would not be configured automatically and would be missing from the "liveness" and "readiness" health groups, leading to 404s when hitting the `/actuator/health/liveness` or `/actuator/health/readiness`. This commit ensures that the health indicators beans have the proper name and revisits the auto-configuration conditions to reflect that as well. Fixes gh-22562

view details

Brian Clozel

commit sha 6efff7b5854aede81f43129ab3f93582c4052397

Merge branch '2.3.x' Closes gh-22698

view details

dreis2211

commit sha 2bdeba8aaa23f925982897b426328cf55df86fbc

Fix NPE in BeanDefinitionLoader when XML support is disabled See gh-22696

view details

Andy Wilkinson

commit sha 11a296b0684df5caa9e5c0ce91fafb7a3a4efb24

Polish "Fix NPE in BeanDefinitionLoader when XML support is disabled" See gh-22696

view details

Andy Wilkinson

commit sha 86e34dc4a70797f78da1697ad00cc32fcabe06a0

Merge pull request #22696 from dreis2211 * gh-22696: Polish "Fix NPE in BeanDefinitionLoader when XML support is disabled" Fix NPE in BeanDefinitionLoader when XML support is disabled Closes gh-22696

view details

Andy Wilkinson

commit sha 989fc365282659854df10529847a1dbf9c83d775

Polish

view details

Andy Wilkinson

commit sha 1168d8fa742ce432536a983b4159c5c79b1e0beb

Reduce reflection in LoggingSystem to make it more Graal-friendly Closes gh-22594

view details

Johnny Lim

commit sha bd2874de497846f6d786d9f4896994d014b7ef9f

Fix broken links to Micrometer registry docs See gh-22704

view details

Stephane Nicoll

commit sha bc020d95b6eeeee3a186a11a417df2e63b795918

Merge pull request #22704 from izeye * pr/22704: Fix broken links to Micrometer registry docs Closes gh-22704

view details

Stephane Nicoll

commit sha 4082cddce24bd6e60136f584d22f956a83c1afc7

Merge branch '2.1.x' into 2.2.x Closes gh-22705

view details

Stephane Nicoll

commit sha 13f1d00048a7602a60b6b685e2d7150481311600

Merge branch '2.2.x' into 2.3.x Closes gh-22706

view details

Stephane Nicoll

commit sha bb3066f61af75442ee1b5546faf1ef6f64cfb621

Merge branch '2.3.x' Closes gh-22707

view details

dreis2211

commit sha e49e2dfff111c90e2a710749c6a32fef56327615

Use Supplier variants of Assert methods See gh-22699

view details

Stephane Nicoll

commit sha e18198237b508dd8c0bb466ed4eb7f756393e478

Merge pull request #22699 from dreis2211 * pr/22699: Use Supplier variants of Assert methods Closes gh-22699

view details

Andy Wilkinson

commit sha a334134fd0ee72838be265ad48f22ff0cf402ff4

Make Slack build failure notifications more noticeable Closes gh-22709

view details

Andy Wilkinson

commit sha 992deb4647db308d91a55aa8d80aef7651af786b

Merge branch '2.2.x' into 2.3.x Closes gh-22711

view details

push time in 2 months

pull request commentspring-projects/spring-boot

Add autoconfiguration for r2dbc-proxy

@snicoll While writing tests, I found using Option has a problem wrapping ConnectionPool with proxy. This is because @Bean method for ConnectionPool wraps the result of createConnectionFactory(). Therefore, proxy cannot wrap the ConnectionPool. So, I fallback to the original plan to make a hook on createConnectionFactory() to post process configured ConnectionFactory. (which I also applied to creating ConnectionPool)

ttddyy

comment created time in 2 months

push eventttddyy/spring-boot

dreis2211

commit sha a8e6c53c84024e27c403c08891348b8bf7ea225c

Remove version management for exec-maven plugin See gh-22397

view details

Stephane Nicoll

commit sha 8a450c790642e2e1ede4eb931b357c8ea05dab4a

Merge pull request #22397 from dreis2211 * pr/22397: Remove version management for exec-maven plugin Closes gh-22397

view details

Andy Wilkinson

commit sha 85828953bd82ce2e0f1a61847338a1bc32e41241

Perform enablement checks once in BackgroundPreinitializer Closes gh-22406

view details

Sébastien Deleuze

commit sha 66bf684eb6d8d83266fc266648bb157ca19d4b68

Ignore BackgroundPreinitializer in native images BackgroundPreinitializer is not relevant in native images so it is better to ignore it automatically in order to reduce the footprint in such environment. See gh-22392

view details

Andy Wilkinson

commit sha 137ce1a9de6087f26357a6829fa6864b948b641a

Merge pull request #22392 from sdeleuze * gh-22392: Ignore BackgroundPreinitializer in native images Closes gh-22392

view details

Andy Wilkinson

commit sha 179d2c79d6d76cf7f77185e331839da01aee27cf

Avoid trivialising what the reader's learning about Closes gh-22408

view details

Andy Wilkinson

commit sha 21f733b89bdc80d5ed642ab48b07d19531218055

Merge branch '2.1.x' into 2.2.x Closes gh-22409

view details

Andy Wilkinson

commit sha accc1f1ca81dc8bd05b5da2b0848b37c371cb69b

Merge branch '2.2.x' into 2.3.x Closes gh-22410

view details

Andy Wilkinson

commit sha 19ad163486f39ba7d8f05896c0a52ca7912f1bd9

Merge branch '2.3.x' Closes gh-22411

view details

Andy Wilkinson

commit sha 5795caea81ef5d65100406ac0b8a187ed6545087

Reinstate jetty-jndi exclusion in spring-boot-starter-jetty Fixes gh-22241

view details

Andy Wilkinson

commit sha e4b065bdd9f0a0ecd8cd890fc45f8333d5f3471c

Merge branch '2.3.x' Closes gh-22419

view details

Andy Wilkinson

commit sha 0fd567664af5df590dc35d6433bc22911007f6e0

Make DefaultErrorAttributes easier to subclass for message customization Closes gh-22378

view details

Andy Wilkinson

commit sha c90dc87b0b4dc83b10c0fafd061d69da19d063f8

Upgrade to Couchbase Client 2.7.16 Closes gh-22420

view details

Andy Wilkinson

commit sha 43fd27bb71628321b4233f86db231c9052c0ae72

Upgrade to Jackson 2.9.10.20200621 Closes gh-22421

view details

Andy Wilkinson

commit sha c166b5b23e65f4fc1e8e66b26706aeadaf7b81f8

Upgrade to Appengine Sdk 1.9.81 Closes gh-22422

view details

Andy Wilkinson

commit sha dd9c9fa7be69a376accbf0ae5d1cd647f1c27100

Upgrade to Micrometer 1.1.15 Closes gh-22423

view details

Andy Wilkinson

commit sha 83ca02f16da88186c2c206bc78b28d7bb39d427d

Upgrade to Netty 4.1.51.Final Closes gh-22424

view details

Andy Wilkinson

commit sha 775231e3e908459ac2f6406bbec522725a8aa78f

Upgrade to Mysql 8.0.21 Closes gh-22425

view details

Andy Wilkinson

commit sha 1113d5cc23431f6188a0774c55236cfdba720b71

Upgrade to Activemq 5.15.13 Closes gh-22426

view details

Andy Wilkinson

commit sha 50b05ac6522bff8bca506049cfaca57869518c34

Upgrade to Tomcat 9.0.37 Closes gh-22427

view details

push time in 2 months

pull request commentspring-projects/spring-boot

Document properties to enable probe health indicators

I was working on readiness/liveness, so I was only looking them especially they are not enabled by default. But it is even better if all properties are documented on the table there. It is easy for readers to have information there how to enable healthindicators (though other than readiness/liveness are enabled by default). I don't think it is easy for readers to realize there is an appendices that have all properties listed for actuator unless there is an explicit link in the section.

ttddyy

comment created time in 2 months

issue commentspring-projects/spring-boot

Add logging when health groups endpoints(readiness/liveness) return unhealthy response

@wilkinsona Thanks for the pointer.

The logging on the code above only happen when the actual health check logic throws an exception. Some of the healthcheck implementation throws Exception and let here to set DOWN status, but some are constructing response health status in the logic without throwing exception.

The intention for my case is when health check(aggregated) returns non UP state(DOWN, OUT_OF_SERVICE, UNKNOWN), then perform logging. This is because the response of liveness health group(/actuator/health/liveness) will trigger the restart of the application. When it happens, I would like to come back to see application log and find out which health indicator returned non-UP status as well as details if available.

ttddyy

comment created time in 2 months

issue commentspring-projects/spring-boot

Kubernetes readiness probe endpoint returning 404 on Spring Boot 2.3.2

Instead of referencing readinessStateProbeIndicator and livenessStateProbeIndicator, I think you need to set management.health.livenessstate.enabled and management.health.readinessstate.enabled properties introduced by spring-boot 2.3.2. So that, you could use readinessState and livenessState reference.

When management.health.[readiness|livenessstate].enabled properties are set to false(by default), AvailabilityProbesAutoConfiguration creates readinessStateProbeIndicator and livenessStateProbeIndicator beans which need to be referenced as [readiness|liveness]StateProbeIndicator(full bean name).

On the other hand, when properties are enabled, AvailabilityHealthContributorAutoConfiguration creates [readiness|liveness]StateHealthIndicator beans which can be referenced as [readiness|liveness]State.

The problem is in AvailabilityProbesHealthEndpointGroups created by AvailabilityProbesHealthEndpointGroupsPostProcessor, this creates readiness/liveness groups with [readiness|liveness]State. So, if [readiness|liveness]State are not available, groups are created but referenced HealthIndicator beans are not there.

chadlwilson

comment created time in 2 months

issue openedspring-projects/spring-boot

Add logging when health groups endpoints(readiness/liveness) return unhealthy response

This is similar to #22509 to improve root cause analysis when probe endpoints returned non 200 response.

I am migrating k8s http probes to use readiness and liveness health group endpoints(/actuator/health/[readiness|liveness]). When these endpoints return non UP status(other than 200 response), k8s stops traffic or shutdown the pod. When such event happens, k8s http probe only record the returned http status for the reason of its probe failure. This makes hard to investigate WHY readiness/liveness probes returned non 200 response when somebody needs to investigate the failure reason later. Even if k8s could record body of probe response, it would be nicer to have such information in application log.

I wrote this implementation to our services to log information when health endpoints returns non UP response.

@Slf4j
public class LoggingHealthEndpointWebExtension extends HealthEndpointWebExtension {

	public LoggingHealthEndpointWebExtension(HealthContributorRegistry registry, HealthEndpointGroups groups) {
		super(registry, groups);
	}

	@Override
	public WebEndpointResponse<HealthComponent> health(ApiVersion apiVersion, SecurityContext securityContext,
			boolean showAll, String... path) {
		WebEndpointResponse<HealthComponent> response = super.health(apiVersion, securityContext, showAll, path);
		HealthComponent health = response.getBody();
		if (health == null) {
			return response;
		}

		Status status = health.getStatus();
		if (status != Status.UP) {
			Map<String, HealthComponent> components = new TreeMap<>();
			if (health instanceof CompositeHealth) {
				Map<String, HealthComponent> details = ((CompositeHealth) health).getComponents();
				if (details != null) {
					components.putAll(details);
				}
			}
			log.warn("Health endpoints {} returned {}. components={}", path, status, components);
		}

		return response;
	}

}

If HealthEndpointSupport could have logging capability (or HealthEndpointWebExtension and ReactiveHealthEndpointWebExtension for web only), then we don't need to have this custom implementation.

Something like:

boolean enableLogging;

if(this.enableLogging && health.getStatus() != Status.UP) {
  log.warn(...);
}

created time in 2 months

delete branch ttddyy/spring-boot

delete branch : task-executor-builder

delete time in 2 months

PR opened spring-projects/spring-boot

Document properties to enable probe health indicators

Document property names to enable probe(readiness/liveness) health indicators.

<!-- Thanks for contributing to Spring Boot. Please review the following notes before submitting you pull request.

Please submit only genuine pull-requests. Do not use this repository as a GitHub playground.

Security Vulnerabilities

STOP! If your contribution fixes a security vulnerability, please do not submit it. Instead, please head over to https://pivotal.io/security to learn how to disclose a vulnerability responsibly.

Dependency Upgrades

Please do not open a pull request for a straightforward dependency upgrade (one that only updates the version property). We have a semi-automated process for such upgrades that we prefer to use. However, if the upgrade is more involved (such as requiring changes for removed or deprecated API) your pull request is most welcome.

Describing Your Changes

If, having reviewed the notes above, you're ready to submit your pull request, please provide a brief description of the proposed changes. If they fix a bug, please describe the broken behaviour and how the changes fix it. If they make an enhancement, please describe the new functionality and why you believe it's useful. If your pull request relates to any existing issues, please reference them by using the issue number prefixed with #. -->

+2 -2

0 comment

1 changed file

pr created time in 2 months

create barnchttddyy/spring-boot

branch : document-probe-property

created branch time in 2 months

PR opened spring-projects/spring-boot

Use mills to map `awaitTerminationPeriod` in `TaskExecutorBuilder`

Prior to this change, TaskExecutorBuilder used second as its precision to map awaitTerminationPeriod value. This caused a loss of millisecond information in the period. This commit fixes the loss by converting the period to millisecond and use the setAwaitTerminationMillis on executor/scheduler.

<!-- Thanks for contributing to Spring Boot. Please review the following notes before submitting you pull request.

Please submit only genuine pull-requests. Do not use this repository as a GitHub playground.

Security Vulnerabilities

STOP! If your contribution fixes a security vulnerability, please do not submit it. Instead, please head over to https://pivotal.io/security to learn how to disclose a vulnerability responsibly.

Dependency Upgrades

Please do not open a pull request for a straightforward dependency upgrade (one that only updates the version property). We have a semi-automated process for such upgrades that we prefer to use. However, if the upgrade is more involved (such as requiring changes for removed or deprecated API) your pull request is most welcome.

Describing Your Changes

If, having reviewed the notes above, you're ready to submit your pull request, please provide a brief description of the proposed changes. If they fix a bug, please describe the broken behaviour and how the changes fix it. If they make an enhancement, please describe the new functionality and why you believe it's useful. If your pull request relates to any existing issues, please reference them by using the issue number prefixed with #. -->

+5 -1

0 comment

2 changed files

pr created time in 2 months

create barnchttddyy/spring-boot

branch : task-executor-builder

created branch time in 2 months

pull request commentspring-projects/spring-boot

Add autoconfiguration for r2dbc-proxy

@ttddyy I can see a WIP in your last update and the tests have been commented out. Do you need something from us? Thanks a lot for your effort.

@snicoll Thanks for checking. I wanted to check whether the current impl with customizer is ok before I proceed. And since you said ok, I'll finish up the rest of the PR.

ttddyy

comment created time in 2 months

issue openedspring-projects/spring-boot

Add logging for availability state change

Changing availability state(readiness/liveness/etc.) is significant events for application. Currently, there is no logging around the availability state change and this makes it hard to find out what caused the state to change when somebody needs to look back what has happened to the application. So, we would like to capture the state change event in application log.

The caller(event publisher) side can log the event but it is more enforced if ApplicationAvailabilityBean(receiver side) logs the event.

For now, state change logging can be achieved by implementing a custom ApplicationListener like followings.

@Slf4j
@Order(0)  // make sure this listener run before "ApplicationAvailabilityBean"
class AvailabilityStateChangeLoggingListener implements ApplicationListener<AvailabilityChangeEvent<?>> {

  private final ApplicationAvailability availability;

  public AvailabilityStateChangeLoggingListener(ApplicationAvailability availability) {
    this.availability = availability;
  }

  @Override
  public void onApplicationEvent(AvailabilityChangeEvent<?> event) {
    AvailabilityState newState = event.getState();
    AvailabilityState lastState = this.availability.getState(newState.getClass());
    if (lastState != null && newState != lastState) {
      Class<? extends AvailabilityState> stateType = getStateType(newState);
      log.info("AvailabilityState changed. type={}, new={}, last={}, source={}",
          stateType.getSimpleName(), newState, lastState, event.getSource().getClass().getSimpleName());
    }
  }

  @SuppressWarnings("unchecked")
  private Class<? extends AvailabilityState> getStateType(AvailabilityState state) {
    if (state instanceof Enum) {
      return (Class<? extends AvailabilityState>) ((Enum<?>) state).getDeclaringClass();
    }
    return state.getClass();
  }

}

But the caveat is this needs to implement @Order/Ordered to ensure the listener ordering correct to retrieve the last state.

If ApplicationAvailabilityBean logs state change, this custom listener is not needed.

created time in 2 months

CommitCommentEvent

push eventttddyy/spring-boot

Tadaya Tsuyukubo

commit sha 48cf578baea0fc2583e7f4fa47e68e67e500da3d

WIP: Add autoconfiguration for r2dbc-proxy Add autoconfiguration for r2dbc-proxy. Create a proxy of `ConnectionFactory` when: - r2dbc-proxy is in classpath - property is enabled (enabled by default) - r2dbc-proxy listener beans are defined

view details

push time in 2 months

push eventttddyy/spring-boot

Phillip Webb

commit sha 4d37430bfe33ba45c0fa3eccf226c4c833babf58

Use servlet context that can access classloader Update `SpringBootServletInitializer` to use the `ServletContext` that was provided to the initial `onStartup` call rather than the one from the `ServletContextEvent`. This allows the `getClassLoader()` call to complete without throwing an `UnsupportedOperationException`. Fixes gh-21684

view details

Phillip Webb

commit sha 16cab0d83c80a7978bd3bef2894e3ddec466d1ed

Merge branch '2.3.x' Closes gh-21690

view details

Andy Wilkinson

commit sha c0f748e1436cd44af3a79d2d9953665bf060a3bf

Always apply retry plugin but only retry on CI Previously, the retry plugin was only applied on CI as we do not want tests to be retried in local builds. Unfortunately, this arrangement led to test tasks from CI builds having additional doFirst and doLast actions and an additional property. These differences meant that the output from a test task that has run on CI could not be used by a local build. This commit changes our configuration of the test retry plugin so that it is now always applied. To retain the behaviour of only retrying tests on CI, max retries is configured to 3 on CI and 0 for local builds. Closes gh-21698

view details

Andy Wilkinson

commit sha 15ec26171c2b1ca073aafeba6ac6c3a54242b921

Merge branch '2.3.x' Closes gh-21699

view details

Andy Wilkinson

commit sha 24138c104cc95ecf7c469c6fccb205902058c73c

Use highlightjs for syntax highlighting in Asciidoctor's HTML output Closes gh-21701

view details

Andy Wilkinson

commit sha c4faeac4d7b62482b85281c9c4b71e9d610af230

Merge branch '2.3.x' Closes gh-21703

view details

Phillip Webb

commit sha b6474f2ca1aefdae7bc55aaa64bb3ebaaf127a96

Remove accidentally committed hook file

view details

Phillip Webb

commit sha 4a0d37267586af4193271bfae82ff192e6183433

Merge branch '2.2.x' into 2.3.x

view details

Phillip Webb

commit sha c666f0ff05355613761b2ee1d7b80c6ec93b0893

Merge branch '2.3.x'

view details

Phillip Webb

commit sha 4a6e08c8179e945560282c47300d15020ff7810f

Add logging to forward-merge script Add some logging to aid with development.

view details

Phillip Webb

commit sha 39caf45155eb76ff5e986d08774772915a52aa28

Allow forward merge to work with .x patterns Closes gh-21687

view details

Phillip Webb

commit sha ba53d10060a6395e2f6b299eba6f985ddc14564b

Merge branch '2.2.x' into 2.3.x Closes gh-21706

view details

Phillip Webb

commit sha 87a155410b22edd351928849ce7c44b901f73ef9

Merge branch '2.3.x' Closes gh-21707

view details

Phillip Webb

commit sha 10fdd6506310ea0255bf8e05cf422f0dd4ef0ea4

Add prepare-forward-merge script Add a git hook script that can be used to prepare a sensible merge commit message. Closes gh-21688

view details

Phillip Webb

commit sha 7561123cd926332a44c891a15dfce37186390240

Merge branch '2.2.x' into 2.3.x Closes gh-21709

view details

Phillip Webb

commit sha 2fe299f6d0ddbc8e7891422c8c79d50ef538d1a3

Merge branch '2.3.x' Closes gh-21710

view details

dreis2211

commit sha 54f93e9b0f6517d0d7e306942dacd7d0ef855a90

Fix multi-release JAR test on JDK 15 See gh-21605

view details

Stephane Nicoll

commit sha 78165c619dc215d7ec82f28a9e6fe01b293f71a0

Merge pull request #21605 from dreis2211 * pr/21605: Fix multi-release JAR test on JDK 15 Closes gh-21605

view details

Andy Wilkinson

commit sha 20f0b41099d080cda1606a0e8629bd1ac11a075b

Upgrade CI to Docker 19.03.9 Closes gh-21681

view details

Andy Wilkinson

commit sha 97533a53648087ff867c4fd7e2e7000fd1ada0f1

Merge branch '2.1.x' into 2.2.x Closes gh-21682

view details

push time in 2 months

pull request commentspring-projects/spring-boot

Add autoconfiguration for r2dbc-proxy

After discussing with @snicoll we found that ordering of pool/proxy/driver wrapping matters (speaking in URL syntax, r2dbc:pool:proxy:h2 vs. r2dbc:proxy:pool:h2) if someone wants to e.g. measure how many real connections were created/closed by the pool vs. how long a connection is in use by the application.

Yes, the ordering matters, and it can be even r2dbc:proxy:pool:proxy:h2.(though, there is a problem specifying listeners for which proxy to apply since there is only one proxyListener option) I consider most of the case proxy is the outer most wrapper since you want to check the Application behavior. If a user wants to proxy the middle ConnectionFactory, the user needs to wrap it manually, but I think that is more advanced use case. For connection-pool in Spring Boot, it may provide a flag in connection-pool settings which would be specific to proxying the connection-pool with some canned proxy listener such as metrics.

ttddyy

comment created time in 2 months

Pull request review commentspring-projects/spring-boot

Add autoconfiguration for r2dbc-proxy

 ConnectionPool connectionFactory(R2dbcProperties properties, ResourceLoader reso  		@Bean 		ConnectionFactory connectionFactory(R2dbcProperties properties, ResourceLoader resourceLoader,-				ObjectProvider<ConnectionFactoryOptionsBuilderCustomizer> customizers) {+				ObjectProvider<ConnectionFactoryOptionsBuilderCustomizer> customizers,+				ObjectProvider<ProxyListenersProvider> proxyListenersProviders) { 			return createConnectionFactory(properties, resourceLoader.getClassLoader(),-					customizers.orderedStream().collect(Collectors.toList()));+					customizers.orderedStream().collect(Collectors.toList()),+					proxyListenersProviders.getIfAvailable(() -> ProxyListenersProvider.EMPTY)); 		}  	} +	@Configuration(proxyBeanMethods = false)+	@ConditionalOnClass(ProxyConnectionFactory.class)+	@ConditionalOnProperty(prefix = "spring.r2dbc.proxy", value = "enabled", havingValue = "true",+			matchIfMissing = true)+	static class Proxy {

Currently, ConnectionFactoryOptionsBuilderCustomizer provides a way to customize Options on ConnectionFactoryBuilder. So, I could use it as a hook point to add/replace some of the Options.

I wasn't sure it is ok to use customizer facility within Spring Boot, but if that's ok, then here can define a customizer bean (probably with @Order to allow users to run own customizers before and after). Then, it will be pretty much all we need for r2dbc-proxy.

ttddyy

comment created time in 2 months

Pull request review commentspring-projects/spring-boot

Add autoconfiguration for r2dbc-proxy

  package org.springframework.boot.autoconfigure.r2dbc; +import java.util.List; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.Supplier; +import io.r2dbc.proxy.ProxyConnectionFactoryProvider;+import io.r2dbc.proxy.listener.ProxyExecutionListener;

ok, I made not to throw NoClassDefFoundError but I'll go some other way not to use them here.

ttddyy

comment created time in 2 months

Pull request review commentspring-projects/spring-boot

Add autoconfiguration for r2dbc-proxy

 private String determineEmbeddedUsername(R2dbcProperties properties) { 			} 		} +		private void configureIfProxyListenersExist(Builder optionsBuilder, ConnectionFactoryOptions urlOptions,+				ProxyListenersProvider proxyListenersProvider) {+			List<ProxyExecutionListener> proxyListeners = proxyListenersProvider.listeners();+			if (proxyListeners.isEmpty()) {+				return;+			}+			String driver = urlOptions.getRequiredValue(ConnectionFactoryOptions.DRIVER);+			if (!ProxyConnectionFactoryProvider.PROXY_DRIVER.equals(driver)) {+				optionsBuilder.option(ConnectionFactoryOptions.DRIVER, ProxyConnectionFactoryProvider.PROXY_DRIVER);+				String protocol = urlOptions.getValue(ConnectionFactoryOptions.PROTOCOL);+				String newProtocol = StringUtils.isEmpty(protocol) ? driver : driver + ":" + protocol;+				optionsBuilder.option(ConnectionFactoryOptions.PROTOCOL, newProtocol);+			}+			optionsBuilder.option(ProxyConnectionFactoryProvider.PROXY_LISTENERS, proxyListeners);+		}

What here is doing is reconstructing DRIVER and PROTOCOL options.

e.g: r2dbc:h2:mem://... to r2dbc:proxy:h2:mem://...

- DRIVER PROTOCOL
From h2 mem
To proxy h2:mem

This way, the discovery mechanism will create ConnectionFactory for proxy and mysql.

Actually, I think same way may be used for r2dbc-pool via PoolingConnectionFactoryProvider as well.

ttddyy

comment created time in 2 months

pull request commentspring-projects/spring-boot

Add autoconfiguration for r2dbc-proxy

Hi @snicoll I added a commit 9cccc61004fa4616a02d32b3572149675f3f329b.

This uses ConnectionFactoryOptionsInitializer(via ConnectionFactoryConfigurations#createConnectionFactory) to construct ConnectionFactory options used by ProxyConnectionFactoryProvider(r2bc-proxy). Also, added ProxyListenersProvider interface to avoid direct reference to the classes in r2dbc-proxy to make it work when r2dbc-proxy is not available.

If this looks good, I'll cleanup the commits with tests.

ttddyy

comment created time in 2 months

push eventttddyy/spring-boot

Tadaya Tsuyukubo

commit sha 9cccc61004fa4616a02d32b3572149675f3f329b

WIP: Configure r2dbc-proxy listeners via ConnectionFactory Option Populate `ConnectionFactory` options for r2dbc-proxy listeners when those beans are defined.

view details

push time in 2 months

pull request commentspring-projects/spring-boot

Add autoconfiguration for r2dbc-proxy

@snicoll Ok, I'll explore the path for modifying ConnectionFactoryConfigurations#createConnectionFactory with ConnectionFactoryOptions. ProxyConnectionFactoryProvider(ConnectionFactoryProvider impl in r2dbc-proxy) understands proxy-listener options. So, if proxy-listener beans are defined, pass them as ConnectionFactoryOptions, then ConnectionFactories#find() would delegate to ProxyConnectionFactoryProvider for actual ProxyConnectionFactory creation with those proxy-listener beans. I think this way is better since it would make more use of r2dbc-spi infrastructure.

ttddyy

comment created time in 3 months

pull request commentspring-projects/spring-boot

Add autoconfiguration for r2dbc-proxy

Hi @marcingrzejszczak

I wrote a sample listener for tracing here long time ago. Looking at it now, I can cleanup a bit. I'll find a time to update it as for a sample listener impl for tracing.

ttddyy

comment created time in 3 months

more