I have created some interface to a 3rd party service:
#RegisterRestClient
public interface FooService {
#Path("/foo")
#POST
MyResponse foo(MyRequest request, #HeaderParam("X-Bla") String xBla);
...
This is working fine.
But then, I also want to create a "lite" version of the API. I was thinking of MyLiteFoo implements FooService, but I notice that all the annotations need to be redeclared in the implementing class since none are #Inherited?
Added: Can't even implements FooService because Quarkus will complain.
Or is there a simpler approach?
Related
I am using MyBatis Spring Boot Starter version 2.1.3. Ever since moving to Spring Boot 2.2.7 (I've also tried 2.2.8 and 2.3.1 with the same results), I've had a problem using the MockBean annotation to mock a MyBatis interface (e.g. DAO). Let's say I have an interface like this one:
#Mapper
#Repository
public interface OrderDAO {
int insertOrder(#Param("order") Order order);
}
I'd like to execute an integration test and mock this mapper within my OrderService that contains a field of type OrderDAO.
My integration test is annotated with #SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) and contains this field:
#MockBean
private OrderDAO orderDAO;
When I run a test such as this and look at what the references to the OrderDAO objects are, in my integration test I see this:
com.example.dao.OrderDAO$MockitoMock$1819884459
But inside my OrderService class the field is this:
com.sun.proxy.$Proxy179 (org.apache.ibatis.binding.MapperProxy#37d9310e)
So, calls to Mockito.verify obviously don't work because my mock has not been injected into my OrderService class. Now, very oddly, I found that adding this code makes everything work:
#TestConfiguration
static class MockConfig {
#Bean
public OrderDAO orderDAO() {
return Mockito.mock(OrderDAO.class);
}
}
Adding this nested class along with adding the ContextConfiguration annotation on the integration test class, and now the object that gets injected into the OrderService class is the MockitoMock -- the same object that is referenced by the MockBean annotated field in the test class. I didn't have to do this with Spring Boot 1.2.6 and earlier and I couldn't find any reference to a change that would have caused this (although perhaps I didn't search long enough).
So, I am wondering if I am doing something incorrectly, or, am I missing something I should be doing? It seems like this should just work like it did before, which the need for this extra nested TestConfiguration class. Appreciate any insights anyone can provide. Thanks.
As mentioned by ave in the comments, I had to add the name to the mock bean annotation to get it to work
#MockBean(name = "orderDAO")
private OrderDAO orderDAO;
I noticed multiple ways in which developers create an Apache Felix Service. Each of the attached snippets seem to work. Would need some help to understand, which syntax is best for which scenario
Sample 1: Service created without interface
Declaration of Service
D
#Component
#Service(ServiceViaClass.class)
public class ServiceViaClass{
}
Using service via #Reference annotation
private ServiceViaClass serviceViaClass;
Sample 2:Service implementing interface. No value attribute for #Service annotation
- Declaration of Service
#Component
#Service
public class ServiceViaInterfaceImpl implements ServiceViaInterface{
}
Using service via #Reference annotation
private ServiceViaInterface serviceViaInterface;
Sample 3: Service implementing interface with value attribute for #Service annotation
- Declaration of Service
#Component
#Service(ServiceViaInterface.class)
public class ServiceViaInterfaceImpl implements ServiceViaInterface{
}
Using service via #Reference annotation
private ServiceViaInterface serviceViaInterface;
A component implements an interface and publishes itself as a service under that interface, so that clients can find the component using only the interface.
Sample 1 — publishing a service using the concrete type of the component — is nearly always useless. The service can only be found using the concrete type, and if clients can see the concrete type then why not just instantiate it directly rather than get an instance from the service registry??
Sample 2 — publishing a service by implementing an interface and then just adding the #Service annotation — is what you should usually do. When you use #Service and the component directly implements an interface, the build tooling infers that your component wants to be published as a service under that interface.
Sample 3 has the exact same effect at runtime as sample 2, it's just a bit more explicit in the code. Some people prefer this because it's explicit, others (including me) dislike it because it is redundant.
I had been using the WebMvcConfigurerAdapter for a while. Since i could not get all the registered interceptors with the method getInterceptors(), i have switched to WebMvcConfigurationSupport, which has lot of default registered Spring Beans like ContentNegotiationManager, ExceptionHandlerExceptionResolver usw.
Now i have realised that, the very handy DomainClassConverter (which converts the domain class ids to domain class objects by using a CrudRepository) is not registered by default, although i use the annotation #EnableSpringDataWebSupport on my WebConfig class.
When i define this bean explicitly like this, it works then.
#EnableSpringDataWebSupport
#Configuration
public class WebConfig extends WebMvcConfigurationSupport {
#Bean
public DomainClassConverter<?> domainClassConverter() {
return new DomainClassConverter<FormattingConversionService>(mvcConversionService());
}
}
But why EnableSpringDataWebSupport does not work with WebMvcConfigurationSupport?
It looks like configuration classes that extend WebMvcConfigurationSupport directly suffer from SPR-10565. The solution, at least for me, is to extend from DelegatingWebMvcConfiguration instead.
If you're overriding individual callbacks in your configuration class you'll likely want to call the superclass' implementation of the callback as well to ensure it's all handled correctly.
Is it possible to write my own function implementation along usage of spring repositories?
I would like to actually implement the function
getUserByFirstName()
and not get it automagically.
While i still want to get
getUserById()
automagically from spring-data.
1) is it possible?
2) is it possible to achieve logging for all methods spring data automagically generates? (or should i write them manually with
logger.log("entering method ...");
See section 1.3 of the manual for the first requirement:
http://docs.spring.io/spring-data/jpa/docs/1.4.2.RELEASE/reference/html/repositories.html#repositories.single-repository-behaviour
For the second requirement I guess some AOP based solution might work for you well here. See here for example using Spring's AOP support:
logging with AOP in spring?
Yes, you can!!!
There is an amazing feature in Spring data that allows this:
Create an interface with your custom method:
public interface UserRepositoryCustom {
User getUserByFirstName();
}
Make your Spring Data interface extends this new interface, as well as the Spring data crud interface (or JPA, Mongo or whatever spring data interface you're extending):
public interface MySpringDataRepository extends CrudRepository<User, Long>, UserRepositoryCustom {
}
Create a class that implements only your custom interface. The name of the class must be Impl, for instance: UserRepositoryImpl:
public class MySpringDataRepositoryImpl implements UserRepositoryCustom {
public User getUserByFirstName(){
//Your custom implementation
}
}
Now, you only need to inject the Spring data repository in your service and you can use both methods: the spring-data implemented method and your custom implemented method:
#Inject private MySpringDataRepository myRepository;
That's it!!
Look at this section in the documentation:
Spring Data Custom implementations
I would like to add resource handlers. In the forum they use WebMvcConfigurationSupport: http://forum.springsource.org/showthread.php?116068-How-to-configure-lt-mvc-resources-gt-mapping-to-take-precedence-over-RequestMapping&p=384066#post384066
and docs say WebMvcConfigurerAdapter: http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html
What's the difference and which one to use? Both has the addResourceHandlers method I need.
This is my current class:
#Configuration
#EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
public #Override void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources");
}
public #Bean TilesViewResolver tilesViewResolver() {
return new TilesViewResolver();
}
public #Bean TilesConfigurer tilesConfigurer() {
TilesConfigurer ret = new TilesConfigurer();
ret.setDefinitions(new String[] { "classpath:tiles.xml" });
return ret;
}
}
The answer is in the doc you referenced above:
If the customization options of WebMvcConfigurer do not expose
something you need to configure, consider removing the #EnableWebMvc
annotation and extending directly from WebMvcConfigurationSupport
overriding selected #Bean methods
In short, if #EnableWebMvc works for you, there is no need to look any further.
if you use ConfigurationSupport class get ready mind numbing hardwork when trying to serve static resources, because it does not work.
I was recently solving this very same problem when configuring converters and it resulted in quite a long post.
By default Spring Boot uses its implementation of WebMvcConfigurationSupport and does a lot of auto-magic including finding all the WebMvcConfigurer and using them. There is one implementation provided by Boot already and you may add more. This results in seemingly confusing behaviour when the list of converters coming to configureMessageConverters in your implementation of WebMvcConfigurer is already pre-populated from previous configurer.
These types (WebMvcConfigurationSupport and WebMvcConfigurer) have also strikingly similar interface - but the first does NOT implement the other. The point is:
Support class searches for configurers and uses them + does something on its own.
If you extend from WebMvcConfigurationSupport you take over the configuration and while there are some things available that are not in WebMvcConfigurer (like addDefaultHttpMessageConverters) there is also tons of code from EnableWebMvcConfiguration and DelegatingWebMvcConfiguration that does not happen.
Both extending WebMvcConfigurationSupport or WebMvcConfigurer (not sure both at once makes much sense) have their valid usages, but with extending the support class you take over the process much more and lose a lot of "opinionated" Spring Boot functionality.
Its better to extend WebMvcConfigurationSupport. It provides more customization options and also
works fine with
configureMessageConverters(List<HttpMessageConverter<?>> converters)
cause you can add these convertors using
addDefaultHttpMessageConverters(converters);
that is not available with WebMvcConfigurerAdapter.
Click [here] How to configure MappingJacksonHttpMessageConverter while using spring annotation-based configuration?
If you extend WebMvcConfigurerAdapter, it behaves strangely with configuring Jackson and Jaxb.
That happened with me !!!