3

It seems to me that having annotations in different order breaks my build.

Does annotations order matter?

Answers from above say, in general, annotations order should not matter. In my case it is breaking.

This is module commons

@ConditionalOnProperty(value = "calculatorEnabled", havingValue = "true")
@Component
class Calculator {

// some logic
}
@ConditionalOnBean(Calculator.class)
@Service
class CalculationService {

    private final Calculator calculator;

    @Autowired
    public CalculationService(final Calculator calculator) {
        this.calculator = calculator;
    }
 // some logic
}
@RequestMapping(value = "/calculations", produces = MediaType.APPLICATION_JSON_VALUE)
@ConditionalOnBean(CalculationService.class)
@RestController
class CalculationController {

}

let there be another module - advanced-calculations

which has module commons as a dependency (maven dependency).

Please, note, there are two maven modules on purpose. So CalculationController is available in other modules that use commons dependency.

Now, let me have two tests in advanced-calculations. (Again, I decided to test CalculationController) in another module.

I know that it is better to have tests in the module that actually defines a component, but commons module was written by other team long time ago; and for now we have to use it.

I want to make sure if we update version of commons, the app should not break (API should not change). Therefore, I added integration tests for CalculationContrioller into advanced-calculation module.

@SpringBootTest(classes = [AdvancedCalculationApplication.class],properties = ["calculatorEnabled=true" ])
@AutoConfigureMockMvc
AdvancedCalculationsITTest extends Specification {

}

and

@SpringBootTest(classes = [AdvancedCalculationApplication.class],properties = ["calculatorEnabled=" ])
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@AutoConfigureMockMvc
AdvancedCalculationsITTestsDisabled extends Specification {

}

mvn clean install fails because AdvancedCalculationsITTest fails. Error cannot autowire CalculationController because there is no candidate calculationService.

However, when I change slightly order of annotations, it works

@ConditionalOnBean(CalculationService.class)
@RequestMapping(value = "/calculations", produces = MediaType.APPLICATION_JSON_VALUE)
@RestController
class CalculationController {

}
Yan Khonski
  • 12,225
  • 15
  • 76
  • 114

1 Answers1

0

I will update this answer, but a bit later.

For me TODO. (I will make a demo and add a link to github and put some code examples).

Your ideas and suggestions are welcome!

I have 2 custom annotations (RUNTIME) on a method: one annotation that makes a method always to throw an exception @Exceptional, another @Catchable that always catches an exception. Let this method return void for simplicity. By placing these annotations in different order, you should get a different result.

@Catchable
@Exceptional
public void processAction() {
    // There is nothing that throws an exception.
    safeStatement1();
    safeStatement2();

    safeStatementN();
}

vs

@Exceptional
@Catchable
public void processAction() {
    // There is nothing that throws an exception.
    safeStatement1();
    safeStatement2();

    safeStatementN();
}

By having these annotations in different order, the result should be different.
Yan Khonski
  • 12,225
  • 15
  • 76
  • 114