Can I make Spring supply #Autowired constructors with nulls while a Bean is feature-toggled off? - spring

I am developing a new feature that should be hidden behind a FeatureToggleX. As part of that, I need to add a new dependency b to my SomeClass:
class SomeClass {
private OldDependency a;
private NewDependency b;
#Autowired
public SomeClass(OldDependency a, NewDependency b) {
this.a = a;
this.b = b;
}
}
I use a custom IfActive annotation as Conditional that serves TheToggledDependency if, and only if, FeatureToggleX is active:
#Component
#IfActive("FeatureToggleX")
class TheToggledDependency implements NewDependency {
}
How can I make Spring temporarily wire b = null while FeatureToggleX is off?
Is there a clean way to plug a generic solution into Spring's wiring process that detects IfActive components and supplies nulls in their places?
As recommended in other answers, I considered #Autowired(required = false) - maybe in combination with overloading SomeClass's constructor - to allow omitting b, but this has the side effect that it also legalizes omitting a, which should be an error.
I could provide an alternative dummy IfInactive variant of NewDependency, but that would fill my project with worthless dummies that I need to remember removing when the toggle is removed.
Similarly, I could build two variants of SomeClass, one that has NewDependency and a second that is completely unaware of it, and choose between the two depending on the toggle. However, that is impractical for larger classes because it duplicates other, unaffected functionality.

No, at least not in the constructor. One way to deal with this kind of things is setter injection.
So you would have something like this (duck-typing here):
class SomeClass {
private OldDependency a;
private NewDependency b;
#Autowired
public SomeClass(OldDependency a) {
this.a = a;
}
#Autorired(required=false)
public void setNewDependency(NewDependency b) {
this.b = b;
}
}
I hope this helps.

Related

Feature envy, encapsulation, active record, separation of concerns? When its bad?

you all say, object oriented programming is about encapsulation, data hiding. Let's given this example:
class Rectangle
{
private int a,b;
public function __construct(int a, int b)
{
this.a = a;
this.b = b;
}
int public function getA()
{
return a;
}
int public function getB()
{
return b;
}
}
var r = new Rectangle(3, 4);
var area = r.getA() * r.getB();
this is a bad code then, so let's refaktor:
class Rectangle
{
private int a,b;
public function __construct(int a, int b)
{
this.a = a;
this.b = b;
}
int public function getArea()
{
return a*b;
}
}
r = new Rectangle(3, 4);
area = r.getArea();
way better, data hiding is done and getArea is brought where it belongs to.
Ok then, here comes the Active Records:
class Record
{
private int ID;
private string username;
public function __constructor(int ID, string username)
{
this.ID = ID;
this.username = username;
}
int public function getID()
{
return ID;
}
string public function getUsername()
{
return username;
}
}
r = new Record(1, 'test');
dbEngine.save(r);
this is again bad, since all data is public. (altough Doctrine works this way)
But if I do that as Propel did:
class Record
{
private int ID;
private string username;
public function __constructor(int ID, string username)
{
this.ID = ID;
this.username = username;
}
public function save()
{
dbEngine.save([ID, username]);
}
}
r = new Record(1, 'test');
r.save();
this is also said bad, because Active Records are antipattern. Then when it's good or bad? When does an "act" (getArea, save) should be brought inside an object - and when does it act outsidely?
You can inject the dbEngine dependency in for your specific case, but this doesn't address your concern.
In general, what makes your code good is how easy it is to understand, and how close changes in intention are tied to changes in implementation.
The problem with revealing private internals are that you're exposing your inner values that programs which interface with your program may rely on (and make difficult to change later on). A record is basically a struct/dataclass - it represents a collection of values that goes together with some well-defined meaning. Without knowing the rest of the code I can't say if this specific class is like that, but if that's the case it would be okay to just make it a struct (all members public, no methods).
There aren't any catch-all rules that makes code 'good'. It's a continuous process of making mistakes or being inefficient, and analysing what code led or made more likely that problem. Code smells are just the result of lots of trial and error by others, and although very robust in most cases may sometimes be outdated and should be applied in the specific situation when they improve your code.
None of your examples are bad. They are just design choices. Dropping the accessors to a and b in the second example seems a step backwards to me. As to putting implementation dependent save code in the class definition, that would be bad if there were multiple types that all needed to define the save. There you would be better to define a parent class with the save function and then inheriting from that class. However, if it’s just you writing code and there is just that one class it doesn’t matter.
Good that you are thinking about what makes good code. As a general rule, good code is code that works and which you can return to in 6 months and modify easily in the future. If you have a group of developers then of course provide accessors.
Another aspect of good code is having unit tests. If you change something and the unit tests pass you’ve done your job. If someone is using internals they should write a unit test that will signal a change that would break their code.

Autowiring interface vs class

If there are more than one implementation of an interface, then I would have to use #Qualifier to indicate which class I want to autowire with. Wouldn't it make more sense to autowire the class directly instead of interface?
This is what object oriented programming (especially abstraction and polymorphism) is about.
You build the classes independendent of concrete implementations and use an interface.
This allows you to change what implementation you use at any point.
Assume you have this:
public interface I{
void doSomething();
}
#Component("a")
public class A implements I{
public void doSomething(){
//...
}
public void doSomethingElse(){
//...
}
}
#Component("b")
public class B implements I{
public void doSomething(){
//...
}
}
If you use
#Autowired
private A yourVariable;
you might be tempted to use the doSomethingElse() method that is an implementation detail (by what reason whatsoever).
However, if you use
#Qualifier("a")
private I yourVariable;
this cannot happen as the method is not present in the interface.
This gives you the ability to swap the implementation at any time.
Wouldn't it make more sense to autowire the class directly instead of interface?
This pretty much depends on how exactly do you work with qualifiers but in general, the answer is "No", autowiring the class is a bad thing to do if you have an interface - you should always work by interface.
Here are the examples:
interface I { void foo(); }
class IImpl1 implements I {
void foo() {System.out.println("Impl1");
pubic void bar() {// another method - why not?}
}
class IImpl2 implements I { void foo() {System.out.println("Impl2"); }
Note, that an implementation IImpl1 has an additional method bar that doesn't belong to the interface I
Case 1:
#Component
public class Driver {
#Autowired
private IImpl1 i;
}
Here class Driver is tightly could to the concrete implementation IImpl1 in general I can call method bar from the Driver class because I have this implementation, but in this case if I'll have to switch the implementation of Driver in future you'll have to also change the code: both change the reference, and also get rid of calls to IImpl1.bar() that might be not that easy to do - its a change in logic. As a result, the whole polymorphic behavior is lost.
By far its the worst way to program.
Now, consider Case 2:
#Component
public class Driver {
#Autowired
#Qualifier("someLogicalName") // under the hood it spring will map it to IImpl1 but you don't know that here
I i;
}
In this case - the things are much better - you never couple the driver to the concrete implementation at the level of code. This means that in general its enough to change the qualifier to get another implementation. You can't call bar anymore - it won't compile.
You also do not know what the implementation will be injected. If in future the implementation of the component that actually implements the logic of "someLogicalName" will change (by that I mean that you'll create a new class IImpl3), you won't feel it here - you'll place that qualifier on that new class and all the places that use it will get that implementation automatically.
Case 3:
#Configuration
public class MyConfiguration {
#Bean
public Driver driver(#Qualifier("someLogicalName") I i) {
return new Driver(i);
}
}
public class Driver {
private final I i;
public Driver(I i) { // in real life this constructor can be generated by
// lombok or something, put it here for the sake of completeness
this.i = i;
}
}
This by far the most "clean" approach - conceptually its really similar to case 2, however in this case you don't place the qualifier at the level of Driver class at all, in fact, the class Driver is not even aware at the level of code / metadata that its related to Spring anyhow. Of course all the "advantages" of case 2 are also applicable here as well.

mock autowired field in#Import class

I am doning an unit test which require some objects which injected by spring so I use:
#RunWith(SpringRunner.class)
#Import({BConfig.class})
public class ATest {
private A a;
#Autowired
private B b;
#Before
public void init() {
a = new A(b);
}
}
However, the BConfig class has an autowired field c which I don' need in this test:
class BConfig {
#Autowired
C c;
#Bean
public getB() {
return new B();
}
// other method code will use field c
}
The autowired c field will get data from redis in #PostConstruct which don't exist in unit test. If I don't omit that, the unit test will report error due to redis data is not exist.
I have a solution to make C to 2 subclasses CProduction and CUnitTest both of them implements interface C, then active profile to use CUnitTest in unit test. However this is some kind of invasive because if don't do the unit test, the interface of C is useless.
Is there a better way to do this?
Consider using:
#RunWith(SpringRunner.class)
#ContextConfiguration({BConfig.class})
class ATest {
#MockBean // will place a mock implementation of C to the context instead of real one that tries to connect with Redis.
C c;
...
}
Note that it will work seamlessly if C is an Interface. Otherwise it will try to create a proxy by inheritance (something that extends from C) and if C has some redis-related code in constructor it might still attempt to call it.
Update 1
Based on OP's comment in an attempt to clarify the answer:
When spring application context starts it basically resolves all the beans and injects what's needed.
First it resolves the bean definitions (metadata) - the real class, scope, etc.
And then it creates beans in the order that will allow injection. For example, it class A has a field of class B (both are beans) then spring must create B first, then create a and inject B into A.
Now, #MockBean is a hook relevant for tests. It tells spring application context used in test that instead of a regular bean definition that spring is able to parse out of #Configuration classes or find the component due to #Component annotation placed on it, it should use the Mock - something that is generated in runtime with frameworks like Mockito.
This mock implementation can later be used to specify the expectations (see Mockito basic tutorial, there are plenty of those on internet), but what's more important for your case, it wont connect to redis because this mock implementation doesn't have any redis related code.
Update 2
The configuration should be rewritten as follows:
#Configuration
public class BConfig {
#Bean
public getB() {
return new B();
}
#Bean
public C c() {
return new C();
}
// other method code will use field c:
// if for example D uses C: then you can:
#Bean
public D d(C c) {
return new D(c);
}
}

code to run before #Autowired is happening

I want to run some lines of code before this line runs:
#Autowired
private SomeClass a;
I'm working on a testing class, I tried #Before, but the #Autowired runs before the code in the #Before, so there is another solution to run code before the autowiring is happening?
This is the code:
Test class:
private classX x;
#Mock
private classA a;
#Autowired
private classB b;
#Before
private void setUpMockResponse() {
when(a.getMeB()).thenReturn(b);
}
classX code:
// Constructor of classX class.
public classX(classA a) {
this.a = a;
this.b = a.getMeB();
}
If there is any solution to the problem I would be happy to see,
the problem is that i need the code in the setUpMockResponse to happen before the autowiring to the classX happens because in the constructor i get b from method on a which is a mock so i need to first set a response when calling the method getMeB(), and also i need b to be autowired.
Sounds like a bad idea to me but who am I to judge? If you want to run code before a dependency is injected, I would write your own setter method and put the #Autowried on the setter, then putting the code before the assignment within the setter:
#Autowired
public void setA(A a)
{
// TODO - put code here
this.a = a;
}
Other option is putting this in an aspect for the setter.
Please note I don't recommend any of these options just trying to answer your question, doing this sort of stuff leads to torturing the next poor soul that comes across this. You won't always need to use Spring in your tests hopefully.

How to wire them together by Spring annotations

I got a web application, and I have to wire it's components (A,B,C) together instead of direct method calls.
So, I dont know how can I wire object instances together when they need additional instances in the constructor.
I think in thats why the we can use (bean ... constructor-args ...) in application context.
But I dont know what if I want to use annotations.
I made a simple example to demostrate the concrete problem
class A
{
protected B b;
...
public func1(){
obj0 = makeObj0();
b = new B(obj0)
}
public Obj0 makeObj0() {...}
}
class B extends C
{
protected Obj0 obj0;
public B(Obj0 obj0){
super(obj0, "foo", new Obj1); //there is no another way to construct B, C
setObj0(obj0);
}
public void setObj0(obj){ obj0=obj;}
}
What is the best way to wiring A,B,(C) together (by annotations) because B, C needs additinal arguments right in their constructor.
Sorry for the lenghty explanation, and thanks for the tips in advance.
Cs
#Autowired
public B(..) {..}
will autowire all arguments. If you need additional arguments - then don't use constructor injection. Use setter/field injection. Provide an empty constructor and have #Autowired on each field that you need.
Hmm.. if you try with #Resource when initiating the B-class.
class A
{
#Resource(name = "b")
protected B b;
...
public func1(){
obj0 = makeObj0();
b = new B(obj0)
}
public Obj0 makeObj0() {...}
}
Then if you need to Autowire in B or C I find hard to tell.

Resources