Annotations on Interfaces in Spring - spring-mvc

I have problems autowiring beans which are derived from interfaces with annotations.
#Component
#EnableAsync
public interface Calculator {
#Async
public Future<String> calculate();
}
public interface SpecificCalculator extends Calculator {
}
public class ConcreteSpecificCalculator implements SpecificCalculator {
#Override
public Future<String> calculate() {
// do calculation here
return new AsyncResult<String>("hello");
}
}
From what I understood from: Annotations on Interfaces? the #Component Annotation should also apply to all subclasses. Now I have a Mapper class returning all types that are derived from SpecificCalculator.
#Component
public class CalculatorMapper {
#Autowired
private List<SpecificCalculator> specificCalculators;
public List<Calculator> retrieveCalculatorsByModuleId(Integer moduleId) {
if(moduleId==...){
return specificCalculators;
}else{
...
}
}
This is not working. Spring does not find the ConcreteSpecificCalculator and is not injecting it. If I Annotate ConcreteSpecificCalculator with #Component again, it is working. Can anybody explain this to me?

Related

In 2 different ASP.Net Core API Controllers, how to ensure same endpoints are defined?

I have a requirement to have 2 data api's both of which should have same methods or endpoints to be implemented.
For example, we can have an interface to make sure, two classes will have same functions. Otherworldly, you define the contract.
public interface ITest
{
void Foo();
}
public class Test : ITest
{
public void Foo()
{
// Some logic
}
}
public class OtherTest : ITest
{
public void Foo()
{
// Some other logic
}
}
Similarly, I want controllers which will have routes and methods like below. Say in one a new action is added, the code should enforce it in the other controller.
DemoController
-- GET demo/api/action1
-- GET demo/api/action2
TestController
-- GET test/api/action1
-- GET test/api/action2
How to achieve this?
Well, you've sort of answered your own question, really. If you want to ensure that the same methods are implemented on multiple classes, that is what interfaces are for. You just make each controller implement the same interface and you're good to go.
As for ensuring a similar routing structure, you can use inheritance for that. Define a base abstract controller class. You can either choose to implement your interface here, and "implement" the required methods as abstract. Any derived class will be forced to implement any abstract methods on the base class, so it has the same effect as an interface. That technically means you can forgo the interface, if you want, and just rely on the base class forcing the implementation. Up to you. Then you can apply route attributes to your abstract methods like so:
[Route("[controller]/api")]
public abstract BaseApiController : ControllerBase
{
[HttpGet("action1")]
public abstract IActionResult Action1();
[HttpGet("action2")]
public abstract IActionResult Action2();
}
if you are dealing with different entities that requires similar business logic, you can create generic base controller and inject your common dependencies as well:
[Route("api/[controller]")]
[ApiController]
public class GenericBaseController<T> : ControllerBase where T : class
{
private readonly ILogger _logger;
public GenericBaseController(ILogger<GenericBaseController<T>> logger) {
_logger = logger;
}
[HttpGet("get")]
public IActionResult Get()
{
//...
}
[HttpPost("post")]
public IActionResult Post(T value)
{
//...
}
}
then you can extend the generic controller :
[Route("api/[controller]")]
[ApiController]
public class MyFirstController : MyFirstController<FirstModel>
{
public GenericBaseController(ILogger<MyFirstController> logger) : base(logger)
{
}
}
another one:
[Route("api/[controller]")]
[ApiController]
public class MySecondController : GenericBaseController<SecondModel>
{
public MySecondController(ILogger<MySecondController> logger) : base(logger)
{
}
}
You don't have to re-create the methods for each inherited controller if it is the same logic, or you may extend any of it if you need:
[Route("api/[controller]")]
[ApiController]
public class MyThirdController : GenericBaseController<ThirdModel>
{
public MyThirdController(ILogger<MyThirdController> logger) : base(logger)
{
}
[HttpPost("post")]
public IActionResult Post(ThirdModel value)
{
// do some logic...
return base.Post(value);
}
}

How do I register a HandlerInterceptor with constructor dependencies in Spring Boot

My use case is running custom code before a controller method by annotating methods.
HandlerInterceptor seems the way to go but it seems impossible to inject dependencies into it because it needs to be registered before the context is being created.
All examples I've found so far use empty constructors (see spring boot adding http request interceptors) or autowire properties in the configuration which fails because I declare dependent beans in the same configuration (Requested bean is currently in creation: Is there an unresolvable circular reference?).
Is there a better way that does not involve AOP?
Assume that your interceptor has constructor dependencies like that:
public class CustomInterceptor extends HandlerInterceptor {
private final DependentBean bean;
public CustomInterceptor(DependentBean bean) {
this.bean = bean;
}
}
Then you can register your handler like that:
#Configuration
public WebConfig extends WebMvcConfigurerAdapater {
#Bean
public DependentBean dependentBean() {
return new DependentBean();
}
#Bean
public CustomInterceptor customInterceptor() {
return new CustomInterceptor(dependentBean());
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(customInterceptor());
}
}
#Configuration will ensure each Bean method call return the same bean instance
Building on the answer above from Mạnh, if using component scan for dependency injection of the dependency, then that can be Autowired in the WebConfig
#Configuration
public WebConfig extends WebMvcConfigurerAdapater {
#Autowired
DependentBean dependentBean;
#Bean
public CustomInterceptor customInterceptor() {
return new CustomInterceptor(dependentBean);
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(customInterceptor());
}
}
Also building on previous answers, and if you use Lombok, you can further simplify.
Have your interceptor implementation been a #Component
Add a private final DependentBean field to it.
Also add a #RequiredArgsConstructor annotation to it, to have Lombok generating a constructor with a single DependentBean parameter.
In your WebConfig, use the same technic to have a private final CustomInterceptor field been injected by Spring IOC.
This way the CustomInterceptor instance will be available & initialized the right way when addInterceptors will be called
Here are the corresponding code samples :
The CustomInterceptor :
#Component
#RequiredArgsConstructor
public class CustomInterceptor implements HandlerInterceptor {
private final DependentBean dependentBean;
#Override
public boolean preHandle( final HttpServletRequest request,
final HttpServletResponse response,
final Object handler ) throws Exception {
// your Interceptor Implementation goes here ...
}
}
The WebConfig :
#Configuration
#RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
private final CustomInterceptor customInterceptor;
#Override
public void addInterceptors( final InterceptorRegistry registry ) {
registry.addInterceptor( customInterceptor );
}
}

How to define javafx callback with no prarameter

I don't know how to define a callback that doesn't need any parameter. In order to describe the question, let me make up a setup - mine is different but contains several more classes, harder to digest.
Lets say we have
public class CustomerA {
public Payment payWithCash() {...}
}
and
public class CustomerB {
public Payment payWithCreditCard() {...}
}
and in addition
public abstract class Factory {
public Callback<Void, Payment> getPaymentCallback();
// Some other methods
...
}
then here comes the problem: I'd like to implement something like this
public class CashFactoryA extends Factory {
public Callback<Void, Payment> getPaymentCallback() {
return CustomerA::payWithCash;
}
}
and in a different class
public class CashFactoryB extends Factory {
public Callback<Void, Payment> getPaymentCallback() {
return CustomerB::payWithCreditCard;
}
}
What happens is, that the compiler complains, that CustomerB does not define payWithCreditCard(Void) and CustomerA likewise fails for payWithCash(Void).
So how to state this correct that there is no parameter to the Callback?
I am aware that I could probably solve my problem as well with interfaces, but I like to understand how to solve this with a Callback.
Thank you in advance!
Consider making Factory generic:
public abstract class Factory<T> {
public Callback<T, Payment> getPaymentCallback();
// Some other methods
...
}
And then you can do
public class CashFactoryA extends Factory<CustomerA> {
public Callback<CustomerA, Payment> getPaymentCallback() {
return CustomerA::payWithCash;
}
}
and
public class CashFactoryB extends Factory<CustomerB> {
public Callback<CustomerB, Payment> getPaymentCallback() {
return CustomerB::payWithCreditCard;
}
}
EDIT:
This answer is a wrong approach.
First, you are trying to refer payWithCash from not a instance of CustomerA but the class CustomerA, so payWithCash must be static method.
public class CustomerA {
public static Payment payWithCash() {...}
}
Then use lambda expression which is the same interface as your Callback.
public class CashFactoryA extends Factory {
public Callback<Void, Payment> getPaymentCallback() {
return param -> CustomerA.payWithCash();
}
}
The code above has the same meaning as the code below. The param argument will be ignored as a result.
public class CashFactoryA extends Factory {
public Callback<Void, Payment> getPaymentCallback() {
return new Callback<Void, Payment>(){
#Override
public Payment call(Void param) {
return CustomerA.payWithCash();
}
};
}
}

autowiring selective beans into a list reference

I have a service interface I with implementaions I1,I2,I3...I10 out of which I want to use I1-I5 to be autowired as a List<I> in controller class C. The I6-I10 should not be be autowired. How can I achieve this. Moreover the I implementations are annotated #Service beans. I do not want to move them to xml declarations.
Based on the comment by mvb13 I have tried to weave a solution for the problem....
So I write a class extending ArrayList and mark it a Component
#Component("mysublist")
public class MyList extends ArrayList implements ApplicationContextAware
{
#Value("comma.sep.eligible.beans.classnames")
private String eligibles;
private ApplicationContext appCtx;
#PostConstruct
public void init()
{
Map allBeans = appCtx.getBeansOfType(I.class);
for(Object bean:allBeans.values())
{
if(eligibles.contains(bean.getClass().getSimpleName()))
{
add(bean);
}
}
}
public void setApplicationContext(ApplicationContext appCtx)
{
this.appCtx = appCtx;
}
}
Now I can autowire the above bean in my required class definition as:
#Service
public class MyService
{
#Resource(name="mysublist")
private List<I> myReqdBeans;
......
}
*Please ignore the generics related implications in the code.
You should use #Qualifier. It defines any subset that you need.
#Autowired
#Qualifier("MySubset")
private List<I> list;
But I think you should move your bean definitions in xml to use <qualifier ... /> property. I think you haven't another option to specify qualifier.
The #Qualifier annotation should give you what you need. You need to apply it in two places:
On the #Service beans that you wish to include in the sub-list
On the #Autowired list injected into your controller
So addressing the #Service beans first:
#Service
#Qualifier("MySubList")
public class MyService implements IMyService
{
}
And then within your Controller:
#Controller
public class MyController
{
#Qualifier("MySubList")
#AutoWired
private List<IMyService> myServices;
}
This instructs Spring to #AutoWire all IMyService implementations #Qualified as "MySubList"

Abstract Factory Method pattern not working with Spring MVC

I have problem with Abstract Factory pattern implementation on Spring. I am using Spring 3 MVC and Hibernate 3, which works fine if I don't use Abstract Factory Method pattern.
I am not sure what I have to add to the Controller to have access the Factory Class (CategoryFactory).
Is there anything missing in the Controller or bean initiating ?
class SectionsController extends MultiActionController {
/* Do I have to initiate the CategoryFactory here? */
public ModelAndView secList() throws Exception {
CategoryFactory.CategoryType type = CategoryFactory.CategoryType.valueOf("view");
modelMap.addAttribute("sectionList", CategoryFactory.findCategory(type).list(id));
return new ModelAndView("Form", modelMap);
}
}
Abstract Factory
public abstract class Category {
public abstract List list(int departId);
}
public class CategoryFactory {
public enum CategoryType { firstclass, secondClass, ... }
public static Category findCategory(CategoryType categoryType) {
// Create type specific Category implementation
}
}
It shoud be:
class SectionsController extends MultiActionController {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public ModelAndView secList() throws Exception {
CategoryFactory.CategoryType type=CategoryFactory.CategoryType.valueOf("view");
modelMap.addAttribute("sectionList",CategoryFactory.findCategory(type).list(hibernateTemplate,id);
return new ModelAndView("Form", modelMap);
}
}

Resources