I tried to use javax.validation.constraints.NotNull with org.springframework.validation.beanvalidation.MethodValidationPostProcessor.MethodValidationPostProcessor but does not run as expected inside the same class. Please, could you tell me why ?
MethodValidationConfig class:
#Configuration
#ComponentScan({ "com.mypackage" })
public class MethodValidationConfig {
#Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
ValidationUtils class:
#Component
#Validated
#Slf4j
public class ValidationUtils {
public void test1(#NotNull String[] test) {
if(test == null) {
log.error("Test is null!!!");
}
}
public void test2() {
test1(null);
}
}
TestApplication class:
#EnableAsync
#EnableTransactionManagement
#SpringBootApplication
#Slf4j
public class TestApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(TestApplication.class, args);
ValidationUtils validationUtils = context.getBean(ValidationUtils.class);
try {
validationUtils.test1(null);
} catch (Exception e) {
log.info("OK");
}
try {
validationUtils.test2();
} catch (Exception e) {
log.info("OK");
}
}
}
com.mypackage.TestApplication : OK
com.mypackage.validationUtils : Test is null!!
I assume the following happens: when you call test1(), the proxy intercepts, and does the validation. When you call test2(), it simply delegates the call to the real object, where there is no proxy involved. Similar problem: Spring AOP not working for method call inside another method
Related
I can't figure out, how to exclude a configuration (e.g. as described here) in a test. What I really want is to ignore a configuration in a #WebMvcTest, but even the following simpler example does not work for me:
#ExtendWith(SpringExtension.class)
#ComponentScan(excludeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {
ComponentScanTest.ExcludedConfig.class }))
class ComponentScanTest {
#Autowired
private ApplicationContext applicationContext;
#Test
void testInclusion() throws Exception { // This test succeeds, no exception is thrown.
applicationContext.getBean(IncludedBean.class);
}
#Test
void testExclusion() throws Exception { // This test fails, because ExcludedBean is found.
assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(ExcludedBean.class));
}
#Configuration
static class IncludedConfig {
#Bean
public IncludedBean includedBean() {
return new IncludedBean();
}
}
static class IncludedBean { }
#Configuration
static class ExcludedConfig {
#Bean
public ExcludedBean excludedBean() {
return new ExcludedBean();
}
}
static class ExcludedBean { }
}
Why is the ExcludedBean found in testExclusion()?
How do I correctly exclude a configuration?
The above test class will pass with the #Profile annotation to control the bean creation.
#ExtendWith(SpringExtension.class)
#ComponentScan
#ActiveProfiles("web")
class ComponentScanTest {
#Autowired
private ApplicationContext applicationContext;
#Test
void testInclusion() throws Exception { // This test succeeds, no exception is thrown.
applicationContext.getBean(IncludedBean.class);
}
#Test
void testExclusion() throws Exception { // This test fails, because ExcludedBean is found.
assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(ExcludedBean.class));
}
#Configuration
#Profile("web")
static class IncludedConfig {
#Bean
public IncludedBean includedBean() {
return new IncludedBean();
}
}
static class IncludedBean {
}
#Configuration
#Profile("!web")
static class ExcludedConfig {
#Bean
public ExcludedBean excludedBean() {
return new ExcludedBean();
}
}
static class ExcludedBean {
}
}
Update : Following code works on #ComponentScan
Create a Configuration class and annotate with #ComponentScan as required
#Configuration
#ComponentScan(excludeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {
ComponentScanTest.ExcludedConfig.class }))
public class TestConfiguration {
}
and provide the ApplicationContext for the test class as follows
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes= {TestConfiguration.class})
class ComponentScanTest {
//.. Everything else remains the same.
}
I have a Spring/Swing application in which I'm experimenting DI but whatever I've done so far, I couldn't make it work properly. Here are some example classes I work on;
public class Launcher {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
ApplicationContext context = null;
try {
context = new AnnotationConfigApplicationContext(AppConfig.class);
MainFrame mainFrame = (MainFrame) context.getBean("mainFrame");
mainFrame.init();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (context != null)
((ConfigurableApplicationContext) context).close();
}
}
});
}
}
#Configuration
#ComponentScan("tr.com.example.*")
public class AppConfig {
#Bean(name = "mainFrame")
public MainFrame createMainFrame() {
return new MainFrame();
}
}
public class MyPanel{
#Autowired
MyManager manager;
...do stuff
}
#Service
public class MyManager{
...do stuff
}
So, when I try to inject MyManager to MyPanel, I'm getting NullPointerException. But if I try to inject it to MainFrame it works.
Can someone please explain me what's wrong here and how should I make it correctly?
Thanks in advance.
Your MyPanel is not a #Component, therefore it's invisible to Spring and any #Autowired or other annotations won't be processed.
The key to Spring is to use it fully. Unless you know that something shouldn't be a bean (i.e. a domain class, entity or so on) it probably should be a bean.
It is not working beacuse you have not use #Component over MyPanel
public class Launcher {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
ApplicationContext context = null;
try {
context = new AnnotationConfigApplicationContext(AppConfig.class);
MainFrame mainFrame = (MainFrame) context.getBean("mainFrame");
mainFrame.init();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (context != null)
((ConfigurableApplicationContext) context).close();
}
}
});
}
}
#Configuration
#ComponentScan("tr.com.example.*")
public class AppConfig {
#Bean(name = "mainFrame")
public MainFrame createMainFrame() {
return new MainFrame();
}
}
#Component
public class MyPanel{
#Autowired
MyManager manager;
...do stuff
}
#Service
public class MyManager{
...do stuff
}
I make my telegram bot using java library TelegramBots, Spring Boot and AspectJ in my application.
I have next class that extend third party library class TelegramLongPollingBot with class TelegramBotPolling.
#Component
public class TelegramBotPolling extends TelegramLongPollingBot {
static {
ApiContextInitializer.init();
}
#PostConstruct
public void registerBot(){
TelegramBotsApi telegramBotsApi = new TelegramBotsApi();
try {
telegramBotsApi.registerBot(this);
} catch (TelegramApiException e) {
logger.error(e);
}
}
#Override
public void onUpdateReceived(Update update) {
...
}
}
This libraries class has abstract method onUpdateReceived that I implement in my class TelegramBotPolling.
I want to keep track when method onUpdateReceived is called and will log this method using Spring AOP:
#Aspect
#Component
public class TelegramBotPollingLogger {
#Around("execution(* ru.cheb.intercity.bus.telegrambot.TelegramBotPolling.onUpdateReceived(..))")
public Object onUpdateReceivedMethodLogger(ProceedingJoinPoint joinPoint)
{
Object returnVal = commonLogHandler.handle(joinPoint);
return returnVal;
}
}
But AOP method onUpdateReceivedMethodLogger doesn't called when onUpdateReceived is called. I think I have a problem because onUpdateReceived relate with third party library. Because my own class methods work well with AOP.
How can I call AOP method onUpdateReceivedMethodLogger when method onUpdateReceivedis called ?
============================================
Trying to inject TelegramBotPolling class in other class:
#Component
public class TelegramBotPolling extends TelegramLongPollingBot implements TelegramBotUpdater{
static {
ApiContextInitializer.init();
}
#Override
public String getBotToken() {...}
#Override
public String getBotUsername() {...}
#Override
public void onUpdateReceived(Update update) {
...
}
}
I define interface TelegramBotUpdater for TelegramBotPolling
public interface TelegramBotUpdater {
String getBotToken();
String getBotUsername();
void onUpdateReceived(Update update);
}
Other class that inject this interface TelegramBotUpdater:
#Component
public class BotRegistrator {
#Autowired
TelegramBotUpdater telegramBotUpdater;
public void register(){
TelegramBotsApi telegramBotsApi = new TelegramBotsApi();
try {
telegramBotsApi.registerBot((TelegramBotPolling)telegramBotUpdater);
} catch (TelegramApiException e) {
logger.error(e);
}
}
}
And Application class that start spring boot application inject other class:
#SpringBootApplication
public class Application {
#Autowired
BotRegistrator botRegistrator;
public static void main(String[] args) throws Throwable {
SpringApplication.run(Application.class, args);
botRegistrator.register();
}
}
When calling botRegistrator.register(); I get NPE exception.
I have a simple Spring Boot web project, right from a template:
#SpringBootApplication
#RestController
public class HelloWorldRestApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldRestApplication.class, args);
Performer p = new Performer();
p.perform();
}
}
I have a test to ensure autowiring works, and in fact it does in this test class (examples come from Spring in Action, 4th):
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerTest {
#Autowired
private CDPlayer cdp;
#Test
public void cdShouldNotBeNull(){
assertNotNull(cdp);
}
}
and:
public class Performer {
#Autowired
private CDPlayer cdp;
public void perform(){
System.out.println(cdp);
cdp.play();
}
public CDPlayer getCdp() {
return cdp;
}
public void setCdp(CDPlayer cdp) {
this.cdp = cdp;
}
}
and:
#Component
public class CDPlayer{
public void play(){
System.out.println("play");
}
}
config:
#Configuration
#ComponentScan
public class CDPlayerConfig {
}
However, it doesnt work in HelloWorldRestApplication, I get null.
Adding #ContextConfiguration(classes=CDPlayerConfig.class) doesn't help.
What do I miss?
Try enabling #ComponentScan your packages in your main class and get Performer class instance from ApplicationContext as below:
#SpringBootApplication
#RestController
#ComponentScan({“package.name.1”,”package.name.2”})
public class HelloWorldRestApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(HelloWorldRestApplication.class, args);
Performer p = ctx.getBean(Performer.class);//get the bean by type
p.perform();
}
}
I have a test class :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = IntegrationTestConfig.class)
#Transactional
#Component
public class AppTest {
#Autowired
private SimpleService simpleService;
#Test
public void test() {
simpleService.test();
}
}
I want make an aspect in order to monitor test method invocation
#Aspect
public class TestAspect {
#Pointcut("#annotation(org.junit.Test)")
public void pointcut() {
}
#After("pointcut()")
public void monitor() {
System.out.println("*** AFTER TEST ***");
}
}
Config :
#Configuration
#ImportResource("classpath:context.xml")
public class IntegrationTestConfig {
#Bean
public TestAspect testAspect() {
return new TestAspect();
}
}
But my monitor method has not been invoked, what's wrong? Generally - can I advice test methods?? I want to know which test method has been invoked.
JUnit itself has Rules that can be used for this.