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.
Related
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);
}
}
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.
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.
In Spring framework and Java world, there is an interesting object collector pattern that I use.
For example consider below -
public interface Calculator {
SomeOutput calculate(SomeInput input);
}
#Component
public class CalImpl1 implements Calculator {
public SomeOutput calculate(SomeInput input){
//some implementation
}
}
#Component
public class CalImpl2 implements Calculator {
public SomeOutput calculate(SomeInput input){
//some implementation
}
}
Now this can easily injected in another class using Spring DI
#Component
public class Main {
//This line collects all to implementors of this and set it here.
#Autowired
public List<Calculator> calculators;
//other methods
}
Now problem is I am not sure how same thing can be achieved in scala. I have done some search and found cake pattern (http://loicdescotte.github.io/posts/scala-di/) used in scala but that didn't seem to achieve same thing as object collectors like above. I also want to follow open close principle which I think gets violated in cake pattern but using object collectors I can easily achieve it.
is there a way achieve same object collectors like implementation in scala?
There are templates in lighbend activator that illustration using spring DI on Play, Akka and Scala applications. Please see this: https://www.lightbend.com/activator/templates#filter:spring
I haven't used Spring as DI, I usually use Guice (explicitly used because it's default on play framework 2) and Implicits parameters both as a compilation DI.
Sample:
class B
class X(x: Int)(implicit c: B)
//DI - mostly define in main method/application
implicit val c: B = new B
val x = new X(2)
Explicitly using java.util.List worked for me. This is not the prettiest solution but it shows that it basically works. Haven't tried that but implementing a corresponding PropertyEditor you could stick with the Scala types.
trait Calculator {
def calculate(input: SomeInput) : SomeOutput
}
#Component
class CalImpl1 extends Calculator {
override def calculate(input: SomeInput): SomeOutput = ...
}
#Component
class CalImpl2 extends Calculator {
override def calculate(input: SomeInput): SomeOutput = ...
}
#Component
class Main #Autowired()(calculators: java.util.List[Calculator]) {
// or inject field if constructor injection is not desired
// #Autowired
// var calculators: java.util.List[Calculator] = _
}
object Main {
def main(args: Array[String]) = {
val ctx = new AnnotationConfigApplicationContext("your package name here")
val main = ctx.getBean(classOf[Main])
// calculators should now be wired in the returned instance
}
}
i want to exclude specific properties of spring rest response body. after hours of googling around i found this: http://www.jroller.com/RickHigh/entry/filtering_json_feeds_from_spring due to its date i like to ask if there is something more up-to-date for jackson and or fasterxml. JsonView doesnt fit my requirements as i need to have such case covered:
if A is the set of all my attributes: one time i need to expose B with B ⊂ A. another time C with C ⊂ A. And B ∩ C != ∅
this would cause complex view declarations as well as annotating every class and might not be possible as well in some cases. so what i would like to do is something similar to this:
#RequestMapping("/test1")
#JsonIgnoreProperties( { "property1"})
public TestObject test1(HttpRequest request){
return new TestObject();
}
#RequestMapping("/test2")
#JsonIgnoreProperties( { "property2"})
public TestObject test1(HttpRequest request){
return new TestObject();
}
with output:
{property2:ipsum,property3:dolor}
{property1:lorem,property3:dolor}
In my opinion Jackson View is what you need.
You have to define three interfaces which should cover all properties:
Public - all common properties.
A - properties which belong to set A.
B - properties which belong to set B.
Example interfaces:
class Views {
static class Public { }
static class A extends Public { }
static class B extends Public { }
}
Assume that your POJO class looks like this:
class TestObject {
#JsonView(Views.A.class) String property1;
#JsonView(Views.B.class) String property2;
#JsonView(Views.Public.class) String property3;
}
Now, your controller should contain below methods with annotations:
#RequestMapping("/test1")
#JsonView(Views.B.class)
public TestObject test1(HttpRequest request){
return new TestObject();
}
#RequestMapping("/test2")
#JsonView(Views.A.class)
public TestObject test2(HttpRequest request){
return new TestObject();
}
All of this I has created without testing. Only by reading documentation but it should work for you. I am sure that similar solution worked for me once.