Add runtime hint

This commit is contained in:
Henning Poettker
2022-11-22 02:49:54 +01:00
parent 2b31713545
commit acdf72b771
2 changed files with 77 additions and 7 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 the original author or authors.
* Copyright 2016-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,9 @@ package org.springframework.cloud.task.batch.listener.support;
import java.lang.reflect.Field;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.batch.core.ChunkListener;
import org.springframework.batch.core.ItemProcessListener;
import org.springframework.batch.core.ItemReadListener;
@@ -36,16 +39,18 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.task.batch.listener.BatchEventAutoConfiguration;
import org.springframework.cloud.task.batch.listener.support.TaskBatchEventListenerBeanPostProcessor.RuntimeHint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.util.ReflectionUtils;
/**
* Attaches the listeners to the job and its steps. Based on the type of bean that is
* being processed will determine what listener is attached.
* <ul>
* <li>If the bean is of type AbstactJob then the JobExecutionListener is registered with
* <li>If the bean is of type AbstractJob then the JobExecutionListener is registered with
* this bean.</li>
* <li>If the bean is of type AbstactStep then the StepExecutionListener is registered
* <li>If the bean is of type AbstractStep then the StepExecutionListener is registered
* with this bean.</li>
* <li>If the bean is of type TaskletStep then the ChunkEventListener is registered with
* this bean.</li>
@@ -64,6 +69,7 @@ import org.springframework.util.ReflectionUtils;
* @author Michael Minella
* @author Glenn Renfro
*/
@ImportRuntimeHints(RuntimeHint.class)
public class TaskBatchEventListenerBeanPostProcessor implements BeanPostProcessor {
@Autowired
@@ -76,8 +82,7 @@ public class TaskBatchEventListenerBeanPostProcessor implements BeanPostProcesso
if (bean instanceof AbstractStep) {
registerStepExecutionEventListener(bean);
if (bean instanceof TaskletStep) {
TaskletStep taskletStep = (TaskletStep) bean;
if (bean instanceof TaskletStep taskletStep) {
Tasklet tasklet = taskletStep.getTasklet();
registerChunkEventsListener(bean);
@@ -150,12 +155,11 @@ public class TaskBatchEventListenerBeanPostProcessor implements BeanPostProcesso
}
private void registerJobExecutionEventListener(Object bean) {
if (bean instanceof AbstractJob
if (bean instanceof AbstractJob job
&& this.applicationContext.containsBean(BatchEventAutoConfiguration.JOB_EXECUTION_EVENTS_LISTENER)) {
JobExecutionListener jobExecutionEventsListener = (JobExecutionListener) this.applicationContext
.getBean(BatchEventAutoConfiguration.JOB_EXECUTION_EVENTS_LISTENER);
AbstractJob job = (AbstractJob) bean;
job.registerJobExecutionListener(jobExecutionEventsListener);
}
}
@@ -169,4 +173,13 @@ public class TaskBatchEventListenerBeanPostProcessor implements BeanPostProcesso
}
}
static class RuntimeHint implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
hints.reflection().registerType(ChunkOrientedTasklet.class, MemberCategory.DECLARED_FIELDS);
}
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2022-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.task.batch.listener.support;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.batch.core.step.item.ChunkOrientedTasklet;
import org.springframework.cloud.task.batch.listener.support.TaskBatchEventListenerBeanPostProcessor.RuntimeHint;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.reflection;
/**
* @author Henning Pöttker
*/
class TaskBatchEventListenerBeanPostProcessorRuntimeHintTests {
private RuntimeHints hints;
@BeforeEach
void setUp() {
this.hints = new RuntimeHints();
new RuntimeHint().registerHints(this.hints, getClass().getClassLoader());
}
@Test
void reflectionOnChunkProviderFieldIsAllowed() {
var field = ReflectionUtils.findField(ChunkOrientedTasklet.class, "chunkProvider");
assertThat(field).isNotNull();
assertThat(reflection().onField(field)).accepts(this.hints);
}
@Test
void reflectionOnChunkProcessorFieldIsAllowed() {
var field = ReflectionUtils.findField(ChunkOrientedTasklet.class, "chunkProcessor");
assertThat(field).isNotNull();
assertThat(reflection().onField(field)).accepts(this.hints);
}
}