I have spring controller with several (REST) endpoints. I want to bring up multiple instances of this controller where each instance would have few endpoints selectively enabled/disabled.
Based on my reading so far, togglz provides feature flipping, but it doesnt enable/disable the REST endpoints (togglz provides API so that caller code can check if a feature is enabled); ff4j seems to be another alternative, but it was not very obvious from the documentation if it can enable/disable REST end points
I read the thread Feature Toggling Java Annotations but it is a longer implementation. Is there any package that I can use to specify the endpoints that need to be enabled/disabled in a configuration file and use annotation on REST endpoints to disable/enable them (this way the logic in my method stays untouched and minimizes the testing)
A class with the #Bean or #Component will be loaded by spring on startup through the bean visitor mechanism. To exclude this bean from the Spring context at startup you can create a BeanPostProcessor(here) and check for dedicated annotation BUT as far as I understand, you cannot put the bean back to the context at runtime.
As a consequence, you must make this bean 'intelligent' to perform the correct operation/mock (or send 503 HTTP code) when requests come in.
FF4j can indeed help you implementing this behaviour but not with a single annotation on top of your REST Controller. What you could do :
Create an interface, annotate the interface with the dedicated FF4J annotation
Create 2 implementations of the interface, each time with a different name
Use FF4J to choose an implementation or another at runtime.
Here some code snippet to get the idea :
public interface GreetingService {
#Flip(name = "theFeatureIDToToggle", alterBean = "greeting.french")
String sayHello(String name);
}
#Component("greeting.french")
public class GreetingServiceFrenchImpl implements GreetingService {
public String sayHello(String name) {return "Bonjour " + name;
}
#Component("greeting.english")
public class GreetingServiceEnglishImpl implements GreetingService {
public String sayHello(String name) {return "Hello " + name;
}
//... import
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:applicationContext-ff4j-aop-test.xml")
public class FeatureAdvisorTest {
#Autowired
private FF4j ff4j;
#Autowired
#Qualifier("greeting.english")
private GreetingService greeting
#Test
public void testAnnotatedFlipping_with_alterBean() {
ff4j.disable("theFeatureIDToToggle");
Assert.assertTrue(greeting.sayHello("CLU").startsWith("Hello"));
ff4j.enable("theFeatureIDToToggle");
Assert.assertTrue(greeting.sayHello("CLU").startsWith("Bonjour"));
}
}
You can toggle a single method or the whole class, as you wish all samples are available here.
Related
I am writing a small CRUD in Spring and Java. And I want to use a separate file for writing logic, this is very convenient for me, I did this when developing with NestJS. I have a few questions, is it correct to do this in Spring, or should I do everything inside a function in the controller. And if I write logic in a separate file, I should mark the logic class as #Component and the functions inside it as #Bean, right? I am new to Spring and as I understand it, I have to do this in order for the application to work correctly and my functions to be in the application context.
AuthLogic.java
#Component
public class AuthLogic {
#Bean
public void register() {
// code ...
}
}
AuthController.java
#RestController
public class AuthController {
#RequestMapping(value = "/register", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public void register(#Valid #RequestBody UserDTO newUser) {
// here I call the register function from AuthLogic
}
}
you can mark your logic class with #Service and use that for example you can make a AuthService and use it like
#Service
public class AuthService{
public returnType login(){
//Logic
}
}
and use this like
#RestController
public class AuthController {
AuthService authService;
#RequestMapping(value = "/register", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public void register(#Valid #RequestBody UserDTO newUser) {
authService.login();
}
}
You can write your business logic in a new separate file at service layer.
Suppose you name it as AuthService and you mark it with annotation #Service.
#Service
public class AuthService{
}
You can then Autowire it in your controller class.
#RestController
public class AuthController {
#Autowired
AuthService authService;
#RequestMapping(value = "/register", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public void register(#Valid #RequestBody UserDTO newUser) {
// here I call the register function from AuthLogic
}
}
Using separate files, or classes more importantly, is very recommended in Spring, and I assume most other languages.
The #Bean annotation on AuthLogic.java is unneeded and I think may cause startup or compilation errors.
I would change the name of AuthLogic to AuthLogicImpl, create an interface named AuthLogic with the method signature void register(), and have AuthLogicImpl implement AuthLogic. Then you can create a constructor for AuthController which accepts and AuthLogic parameter and sets it to a private field (note using the interface not the implementation in the constructor).
At the core of Spring is the IoC container. This container holds "beans" that can be injected or autowired into other beans. These beans are an instance of their class and can be used by other beans. Remember Spring uses the singleton pattern, so your beans should be stateless. This allows Spring to handle the application startup for you, so you don't need to write a ton of code creating all the different services/classes and wiring them together, it's all automagically done for you.
There are two key annoitations that you appear to be confused about:
#Component Putting this above a class will create an instance of that class (a bean) and put it into the IoC container. Other beans can access this by accepting the original beans interface in its constructor. So if I put #Component above my class FooImpl which implements Foo, then I can create a class, BarImpl with the constructor public BarImpl(Foo foo) {this.foo = foo} and BarImpl can use any public method of Foo (which will use FooImpl's implementation).
#Bean this is to be put on a method of a class that is annotated with #Configuration. This tells Spring that this method should be run at startup, and this method will return a bean that Spring should add to the IoC container. This is a popular way of configuring a bean that requires some parameters, such as the bean that manages the connection to a third party service or datastore, especially when that there is a little bit of logic that needs to go into creating the bean.
Note that the above is very broad, and there are some specifics if you need to dig deep into the spring framework, so there will be more clarification in the Spring documentation or you dig into some established Spring project. However it should suffice to answer the broad question of what is going on with #Component and #Bean.
There is no specific layout or code structure for Spring Boot Projects. However, there are some best practices followed by developers that will help us too. You can divide your project into layers like service layer, entity layer, and repository layer.
We use the entity layer to write all model and POJO classes. We annotate them with #Entity.
We use #Repository to indicate that this is a repository interface that is used to do some basic CRUD operations.
Sidenote:- You don't have to write #Repository for classes that implement or interfaces that extends Repository interfaces provided by Spring Boot framework.
We use #Service to say that this is the service class where your all business logic will be present.
We use the controller layer to receive HTTP requests and send back HTTP Responses or views.
You can learn and understand more from here
You can refer to this Image to understand the structure
project structure
Is there a way to autowire an object that needs to be re-instantiated frequently?
I am using Netflix's DGS + spring boot framework, and basically storing the user authentication details in a custom context which is created for each request. I am trying to avoid adding context to the method signature because of the large amount of refactoring needed.
e.g.
public Result dataFetcher(DataFetchingEnvironment dfe) {
// this context contains user details which is used for authorization
// instantiated for every request
setRolesInContext(dfe);
MyCustomContext context = DgsContext.getCustomContext(dfe);
// trying to avoid adding context as an extra param e.g. dataFetcherHelper(context)
dataFetcherHelper(); // this calls other helper methods from other classes
}
I was thinking of using the facade pattern but this would not be thread safe. Basically autowire the RequestContextHolder, and call setRequestContext each time a new context gets initialized.
#Component
#NoArgsConstructor
#Getter
#Setter
public class RequestContextHolder {
private RequestContext requestContext;
}
I'm not sure how your question:
Is there a way to autowire an object that needs to be re-instantiated frequently?
Is related to the use case that you've presented in the question...
From the question it looks like you can consider using ThreadLocals as a conceptual "substitution" to the global variable available all over the place in the request if you don't want to add parameters to the methods to propagate the context through the flow.
This will work only in "thread-per-request" model, it won't work for reactive systems and for the complicated cases where you maintain different thread pools and switch the threads while implementing the Business Logic on backend:
So to achieve "thread-safety" in your context holder that you have suggested you can use:
#Configuration
public class MyConfig {
#Bean
public ThreadLocal<MyCustomContext> ctxHolder() {
return new ThreadLocal<>();
}
}
Then, again, if you're working in thread-per-request model, you can:
#Component
public class DataFetcherInterceptor {
#Autowired
private ThreadLocal<MyCustomContext> ctxHolder;
public Result dataFetcher(DataFetchingEnvironment dfe) {
// this context contains user details which is used for authorization
// instantiated for every request
setRolesInContext(dfe);
MyCustomContext context = DgsContext.getCustomContext(dfe);
ctxHolder.set(context);
dataFetcherHelper();
}
}
In the dataFetcherHelper or in general in any method that requires the access to the context you can:
public class SomeService {
#Autowired ThreadLocal<MyCustomContext> ctxHolder;
public void dataFetcherHelper() {
MyCustomContext ctx = ctxHolder.get();
}
Now, I see that dataFetcherHelper is just a method that you call from withing this "interceptor" class, in this case its an overkill, but I assume, you've intended that this is actually a method that belongs to another class, that might be an element in the call-chain of different classes. For these situations, this can be a working solution.
I have a requirement of compatibility with a new architecture based in Spring 3.2. The requirement is: a http request will come to a controller with an attribute that defines which kind of object is required. For example ...mycontroller/load?objType='obj1'.
My controller will have this structure:
#Controller
public class myController{
private ObjectService objectService;
#Autowired
public setObjectService(ObjectService objectService){
this.objectService = objectService;
}
}
So after that, I need to check this attribute to decide which service will I use. For example, this case is Obj1Service (method: "load"). All this services are extended from ObjectService, so: It is a good idea to swap objectService dependency to Obj1Service / Obj2Service in each incoming call? For example:
if(objType.equals("obj1")) this.setObjectService(context.getBean("obj1Service"..))
if(objType.equals("obj2")) this.setObjectService(context.getBean("obj2Service"..))
I know that is not a great design, but we need to integrate this new modules with other system that produces this kind of http requests.
It is necessary the inheritance because we have very similar behavior in many service's code, but with modifications in internal methods, so part of the behavior will be placed in ObjectService (it is not abstract) and other portion of the code will be placed in it children. Is there another way, more appropriate, to do this? Or you consider that is an acceptable solution?
Thanks!
You can use a map for all of your services, and get the appropriate service inside each controller method.
Let's say you have two services:
#Service("obj1")
public class ObjectServiceImpl1 implements ObjectService {
...
}
#Service("obj2")
public class ObjectServiceImpl2 implements ObjectService {
...
}
In your controller:
private Map<String, ObjectService> objectServices;
#Autowired
public setObjectServices(Map<String, ObjectService> objectServices){
this.objectServices= objectServices;
}
Spring will inject the map with all the ObjectService beans mapped by their names.
In load?objType=obj1 handler, you would have something like:
objectServices.get("obj1").doSomething(); // will use ObjectServiceImpl1
The same with load?objType=obj2 handler:
objectServices.get("obj2").doSomething(); // will use ObjectServiceImpl2
And so on.
I am using Spring, here is a controller:
#Controller
public class PersonController {
#Resource(name="PersonService")
private PersonService personService;
#RequestMapping(value = "/Person", method = RequestMethod.GET)
public String getPersons(Model model) {
// Retrieve all persons by delegating the call to PersonService
List<Person> persons = personService.getAll();
// Attach persons to the Model
model.addAttribute("persons", persons);
//then return to view jsp
}
and here is a service :
#Service("personService")
#Transactional
public class PersonService {
public List<Person> getAll() {
//do whatever
}
}
However, to properly make use of DI I should change the controller to make use of an interface (?) like so:
#Controller
public class PersonController {
#Resource(name="personService")
private IPersonService personService; //Now an interface
}
This would then allow me, for example, to use two services one test and one live. Which I could alter by adding/removing the annotation on the services :
#Service("personService") // this line would be added/removed
#Transactional
public class LivePersonService implements IPersonService {
public List<Person> getAll() {
//do whatever
}
}
and
#Service("personService") //this line would be added/removed
#Transactional
public class TestPersonService implements IPersonService {
public List<Person> getAll() {
//do something else
}
}
However one of the main benefits is lost due to the fact that the code has to be recompiled ? Whereas if I used xml lookup I could alter the dependency on-the-fly ?
The configuration is still external, because it is outside where you define which implementation is going to be injected. Inside the class, you just hardcode the "name" of something the class depends on (which is ok, because this dependency is inherent to the class).
This said, you can use XML to override the annotations of your code for the tests execution (you would have a specific XML application context for your tests) and specify which implementation you will inject.
Therefore, you don't need to change your code to run the tests. Take a look to this answer.
Well that's correct. Annotations are configuration inside the source code. Mainly intended when you have one class for each service. If you have more than one implementation for a particular interface, then XML will be a better option. Also you can mix XML configutation with annotations.
The conventional way, that I heard last time from DI camp, is that in unit tests, you shouldn't use the DI framework. Rather, simply instantiate mock service yourself and set it to the host object
test()
PersonController contr = new PersonController();
contr.personService = new TestPersonService();
// testing contr
This was hailed as the first and major achievement of DI, much to the puzzlement of people (like me) who don't get it. See my previous criticisms: advantage of using applicationcontext.getbean vs #configurable
If the DI supporters in this thread reflect the new trend in DI camp, they no longer do unit tests that way; instead tests depend on DI too, with a test specific DI config. Then it's really no different from service locator pattern. If the major feature of DI is moot, then what's the point?
Your controller class perfectly illustrated that. It cannot be used outside Spring DI framework as a POJO. There's nothing POJO about it. And nobody cares, rightfully. Same thing if your class depends on a service locator framework.
There are other features provided by Spring beans framework, none of them depends on DI; they can be implemented in a service locator framework just as well. Many people when defending DI the design pattern, are actually defending Spring the entire stack. You can actually use Spring as a service locator framework; Spring will not advertise this now, it's a blow to its main hype point; but it will once the hype weakens and it must appeal to the doubters.
We have decided to use Dependency Injection with JSR-330 annotations for our future modularization efforts, and have been very pleased with the first deliverable based on Guice 2 SVN.
Now we need to ensure and document through unit tests that the constructions we need, also work in Spring when configured programmatically (we want the same refactoring support as with Guice so no XML files). I have problems with #Provider and #Inject #Named("foo") String but I have made plain #Inject work with:
ApplicationContext ctx = new AnnotationConfigApplicationContext(LIBL_Object.class,
CORE_Provider.class);
this.object = ctx.getBean(LIBL_Object.class);
where LIBL_Object is the base class to be injected into, but the CORE_Provider does not register as I hoped within Spring.
The implementation of CORE_Provider is
package qa.jsr330.core;
import javax.inject.Provider;
public class CORE_Provider implements Provider<ProvidedInterface> {
#Override
public ProvidedInterface get() {
return new CORE_Provided();
}
}
and I want it injected into
package qa.jsr330.core;
import javax.inject.Inject;
public class LIBL_Object {
private ProvidedInterface provided;
public ProvidedInterface getProvided() {
return provided;
}
#Inject
public void setProvided(ProvidedInterface provided) {
this.provided = provided;
}
// Other stuff omitted.
}
Also we have found that we can pass configuration values very clearly using the #Named tag. This code looks like:
String hostname;
#Inject
public void setHostname(#Named("as400.hostname") String hostname) {
this.hostname = hostname;
}
where we can then register this string with Guice using
bindConstant().annotatedWith(Names.named("as400.hostname")).to(value);
So the two questions are:
How do I register the #Provider class with Spring 3 programatically?
How do I register a string constant with Spring 3 so that #Named selects it properly?
The short answer is: there is no such thing as programmatic configuration of Spring.
Despite the fact that both Spring and Guice support JSR-330 API and that Spring can be configured without XML now, their ideologies are still very different. Spring relies on static configuration, either in the form of XML files or annotated Java classes. Therefore straightforward attempt to adapt Guice-style configuration to Spring may produce difficulties.
Regarding the problem with Provider - Spring doesn't support javax.inject.Provider in the same way as toProvider() binding in Guice (by the way, this usage of Provider is not specified in JSR-330 docs). Therefore some Spring-specific annotations may be needed, for example
#Configuration
public class CORE_Provider implements Provider<ProvidedInterface> {
#Override #Bean
public ProvidedInterface get() {
return new CORE_Provided();
}
}
Binding value coming from the outside may be difficult due to static nature of Spring configuration. For example, in your case, it can be done like this:
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(IBL_Object.class);
ctx.register(CORE_Provider.class);
ctx.registerBeanDefinition("as400.hostname",
BeanDefinitionBuilder.rootBeanDefinition(String.class)
.addConstructorArgValue(value).getBeanDefinition());
ctx.refresh();