I want to know hoew does the annotation from spring #ApiOperation(value = "", hidden = true) works to hide information on my swagger page.
What class is responsible to load the annotation
What does it do with that same values of the annotation.
Where can I find how the annotation works?
The springfox.documentation.spring.web.readers.operation.ApiOperationReader.read(RequestMappingContext) method orchestrates the scanning of methods annotated with #ApiOperation and takes into consideration the hidden flag when doing so, you can see it in the sourcecode over at GitHub.
The specific method that scans the annotated methods and populates the context with the information regarding whether such method should be hidden or not can be found here.
You can keep browsing the source code for more information regarding the implementation, and you can also get more information regarding the #ApiOperation annotation over at https://github.com/swagger-api/swagger-core/wiki/annotations#apioperation.
Related
I downloaded the spring-framework project, because I want to see how #Autowired is implemented.
So, I got to this file, which is an interface.
But when I want in Intellij to go to its implementation, no implementations are found.
So is this interface not implemented?
Then where is the code for #Autowired?
Well, this is not an interface it is actually an annotation.
In java #inteface is used to create an annotation.
Once the annotation is created, you can use that annotation on fields, classes, methods (based on what is specified in #Target of the annotation definition.
Spring does package scanning and finds all the things which are using a particular annotation and does the required processing.
Use this article to undestand more in How an annotation is created, used and the how the annotation processor finds and processes the annotation.
#Autowired doesn't really have much code, so to speak. It's just an annotation which is a Java type of interface that provides instructions to other parts of the codebase.
#Autowired is only an annotation or you can say a "marker". Spring use reflection to identify annotation and do something about that annotated thing. For example with #Autowired, when spring found it, spring will inject the annotated property with eligible bean.
What's the recommended way to run a spring boot test where only the one subject under test is configured in the context.
If I annotate the test with
#RunWith(SpringRunner.class)
#SpringBootTest(properties = "spring.profiles.active=test")
#ContextConfiguration(classes = MyTestBean.class)
Then it seems to work - the test passes, the context starts quickly and seems to only contain the bean that I want. However, this seems like an incorrect use of the #ContextConfiguration(classes = MyTestBean.class) annotation. If I understand correctly the class that I reference is supposed to be a Configuration class, not a regular spring service bean or component for example.
Is that right? Or is this indeed a valid way to achieve this goal? I know there are more complex examples like org.springframework.boot.test.autoconfigure.json.JsonTest which use #TypeExcludeFilters(JsonExcludeFilter.class) to control the context - but this seems overkill for my use case. I just want a context with my one bean.
Clarification
I know that I can just construct the one bean I am testing as a POJO without a spring context test and remove the three annotations above. But in my precise use case I am actually reliant on some of the configuration applied to the context by settings in the application-test.properties file - which is why I've made this a Spring Boot test with a profile set. From my perspective this isn't a plain unit test of a single class in isolation of the spring context configuration - the test is reliant on certain configuration being applied (which is currently provided by the spring boot app properties). I can indeed just test the components as a POJO by creating a new instance outside of a spring context, I'm using constructor injection making the providing of necessary dependencies simple but the test does rely on things like the log level (the test actually makes assertions on certain logs being produced) which requires that the log level is set correctly (which is currently being done via logging.level.com.example=DEBUG in a properties file which sets up the spring context).
For starters, reading the documentation first (e.g., the JavaDoc linked below in this answer) is a recommend best practice since it already answers your question.
If I understand correctly the class that I reference is supposed to be
a Configuration class, not a regular spring service bean or
component for example.
Is that right?
No, that's not completely correct.
Classes provided to #ContextConfiguration are typically #Configuration classes, but that is not required.
Here is an excerpt from the JavaDoc for #ContextConfiguration:
Annotated Classes
The term annotated class can refer to any of the following.
A class annotated with #Configuration
A component (i.e., a class annotated with #Component, #Service, #Repository, etc.)
A JSR-330 compliant class that is annotated with javax.inject annotations
Any other class that contains #Bean-methods
Thus you can pass any "annotated class" to #ContextConfiguration.
Or is this indeed a valid way to achieve this goal?
It is in fact a valid way to achieve that goal; however, it is also a bit unusual to load an ApplicationContext that contains a single user bean.
Regards,
Sam (author of the Spring TestContext Framework)
It is definitely a reasonable and normal thing to only test a single class in a unit test.
There is no problem including just one single bean in your test context. Really, a #Configuration is (typically) just a collection of beans. You could hypothetically create a #Configuration class just with MyTestBean, but that would really be unnecessary, as you can accomplish doing the same thing listing your contextual beans with #ContextConfiguration#classes.
However, I do want to point out that for only testing a single bean in a true unit test, best practice ideally leans towards setting up the bean via the constructor and testing the class that way. This is a key reason why the Spring guys recommend using constructor vs. property injection. See the section entitled Constructor-based or setter-based DI of this article, Oliver Gierke's comment (i.e. head of Spring Data project), and google for more information. This is probably the reason you're getting a weird feeling about setting up the context for the one bean!
You can also use ApplicationContextRunner to create your context using a test configuration of your choice (even with one bean if you like, but as other people have already mentioned for one bean it's more reasonable to use the constructor the classical way without using any spring magic).
What I like this way of testing is the fact that test run very fast since you don't load all the context. This method is best used when the tested bean doesn't have any Autowired dependencies otherwise it's more convenient to use #SpringBootTest.
Below is an example that illustrates the way you can use it to achieve your goal:
class MyTest {
#Test
void test_configuration_should_contains_my_bean() {
new ApplicationContextRunner()
.withUserConfiguration(TestConfiguration.class)
.run(context -> {
assertThat(context.getBean(MyTestBean.class)).isNotNull();
});
}
#Configuraiton
public static class TestConfiguration {
#Bean
public MyTestBean myTestBean(){
new MyTestBean();
}
}
}
I'm reading this official page of Spring documentation and then I read this sentence which I didn't understand :
You cannot add advice to final methods when you use Spring MVC. For
example, you cannot add advice to the
AbstractController.setSynchronizeOnSession() method. Refer to Section
10.6.1, “Understanding AOP proxies” for more information on AOP proxies and why you cannot add advice to final methods.
Can anybody explain to me what they mean by this, and specially by advice?
An advice is a method that should be called before or after a method of another class is invoked.
An example could be a logging advice, that is attached to every method of a service to log out the invocation of every service method.
In order to attach an advice to a method, Spring subclasses the class, the method belongs to and overrides the method with an implementation that calls the advice when the method is invoked. Additionaly the proxy method will also call the overwritten method (the super method) to obtain the original functionality.
A final method cannot be overidden, so Spring cannot create a proxy and you cannat attach an advice.
Its a general limitation, that it is impossible to use a subclass proxy for final methods. It is not a special limitation for aspects.
An advice isn't something specific to Spring MVC, but rather a concept from Aspect Oriented Programming (or AOP for short, see this wikipedia page for a general introduction).
The way Spring Beans work, and the way they allow for AOP, is by taken the class you annotated as a bean, and creating a proxy based on that class, which means on-the-fly / at runtime creating a subclass instance that inherits from your class and which provides custom implementations for each method ('overriding' them). As you know, overriding final methods is inherently impossible (that's what makes them final). That's the reason why the documentation states:
you cannot add advice to final methods
I have been looking at various examples of how to use Spring with REST. Our end target is a Spring HATEOAS/HAL setup
I have seen two distinct methods for rendering REST within Spring
Via #RestController within a Controller
Via #RepositoryRestResource within a Repository
The thing I am struggling to find is why would you use one over the other. When trying to implement HAL which is best?
Our database backend is Neo4j.
Ok, so the short story is that you want to use the #RepositoryRestResource since this creates a HATEOAS service with Spring JPA.
As you can see here adding this annotation and linking it to your Pojo you have a fully functional HATEOAS service without having to implement the repository method or the REST service methods
If you add the #RestController then you have to implement each method that you want to expose on your own and also it does not export this to a HATEOAS format.
There is a third (and fourth) option that you have not outlined, which is to use either #BasePathAwareController or #RepositoryRestController, depending on whether you are performing entity-specific actions or not.
#RepositoryRestResource is used to set options on the public Repository interface - it will automatically create endpoints as appropriate based on the type of Repository that is being extended (i.e. CrudRepository/PagingAndSortingRepository/etc).
#BasePathAwareController and #RepositoryRestController are used when you want to manually create endpoints, but want to use the Spring Data REST configurations that you have set up.
If you use #RestController, you will create a parallel set of endpoints with different configuration options - i.e. a different message converter, different error handlers, etc - but they will happily coexist (and probably cause confusion).
Specific documentation can be found here.
Well, above answers are correct in their context still I am giving you practical example.
In many scenarios as a part of API we need to provide endpoints for searching an entity based on certain criteria. Now using JPA you don't have to even write queries, just make an interface and methods with specific nomenclature of Spring-JPA. To expose such APIs you will make Service layer which would simply call these repository methods and finally Controllers which will expose endpoints by calling Service layer.
What Spring did here, allow you to expose these endpoints from such interfaces (repositories) which are generally GET calls to search entity and in background generates necessary files to create final endpoints. So if you are using #RepositoryRestResource then there is no need to make Service/Controller layer.
On the other hand #RestController is a controller that specifically deals with json data and rest work as a controller. In short #Controller + #ResponseBody = #RestController.
Hope this helps.
See my working example and blog for the same:
http://sv-technical.blogspot.com/2015/11/spring-boot-and-repositoryrestresource.html
https://github.com/svermaji/Spring-boot-with-hibernate-no-controller
#RepositoryRestController override default generated Spring Data REST controllers from exposed repository.
To take advantage of Spring Data REST’s settings, message converters, exception handling, and more, use the #RepositoryRestController annotation instead of a standard Spring MVC #Controller or #RestController
E.g this controllers use spring.data.rest.basePath Spring Boot setting as base path for routing.
See Overriding Spring Data REST Response Handlers.
Be aware of adding #ResponseBody as it is missed in #RepositoryRestController
If you not exposed repository (marked as #RepositoryRestResource(exported = false)), use #BasePathAwareController annotation instead
Also be aware of bags
ControllerLinkBuilder does not take Spring Data REST's base path into account and #RequestMapping shouldn't be used on class/type level
and
Base path doesn't show up in HAL
Workaround to fix link: https://stackoverflow.com/a/51736503/548473
UPDATE: at last I prefer not to use #RepositoryRestController due to lot of workarounds.
Can anyone explain what I need to do to implement my own annotation that would add functionality to my web requests?
For example:
#Controller
public class MyController {
#RequestMapping("/abc")
#RequiresSomeSpecialHandling
public void handleSecureRequest() {
}
}
Here #RequiresSomeSpecialHandling would be my own annotation that causes some special work to be done before or after the given web request /abc.
I know that on a very high level I would need to write a bean post processor, scan classes for my annotations, and inject custom mvc interceptors when needed. But are there any shortcuts to simplify this task? Especially for the two examples above.
Thanks in advance,
This kind of Annotations, (that add additional functionality when invoking a method) looks like annotations that trigger an AOP Advice.
#see Spring Reference Chapter 7. Aspect Oriented Programming with Spring
The idea is to use the Annotation to trigger the AOP Advice.
like:
#Pointcut("#target(com.example.RequiresAuth)")
Depends on what you want to do as a result of #RequiresSomeSpecialHandling. E.g. do you want it to influence request mappings or the invocation of the method (i.e. resolving method arguments, processing the return value)?
The support for annotated classes in Spring 3.1 became much more customizable. You can browse some examples in this repo.
Also keep in mind that a HandlerInterceptor in Spring 3.1 can cast the handler Object to HandlerMethod, which gives you access to the exact method including its annotations. That may be enough for what you need to do.
If caching is one of your goals, take a look at the #Cacheable annotation (and its siblings #CachePut, #CacheEvict and #Caching), available as of Spring 3.1.