#Service
abstract class A {
protected MyObj obj;
protected A(MyObj obj) {
this.obj = obj;
}
public abstract XYZ getTrade();
}
#Service
public class B extends A {
B(MyObj obj) {
super(obj);
}
public XYZ getTrade() {}
}
#Service
public class C extends A {
C(MyObj obj) {
super(obj);
}
public XYZ getTrade() {}
}
#Controller
public class MyController {
#GemMapping("/test")
public void test() {
MyObj obj = new MyObj();
if(condition 1) {
//call getTrade() method of class B
}
if(condition 2) {
//call getTrade() method of class C
}
}
}
MyObj is a user-defined POJO that is not managed bean.
I have the above classes. now I have to call getTrade() method based on some condition in Controller. Could you please help/advise?
this answer is based on the information provided by the question.
to inject beans you could do:
#Controller
public class MyController {
private final B b;
private final C c;
public MyController (B b, C c) {
this.b = b;
this.c = c;
}
.........
}
in this case, beans must have to have one no-args constructor. so, In your case what you can do is have a no-args constructor in each service. then set your myObj by setter. that will do the trick.
If you want to achieve polyformism on your sevices you need to add a Qualifier in your classes B and C. So the question now became how to inject a service dynamically on runtime, and this is answered here:
How to dynamically inject a service using a runtime "qualifier" variable?
Related
Below is my interface :-
interface Student {
findById();
}
Below are my 2 implementations of interface :-
class Matriculation implements Student {
findById(){
//implementation
}
}
class Graduation implements Student {
findById(){
//implementation
}
}
application.properties
graduation=true
Calling class :-
class Test {
#Autowired
Student student ;
method(){
student.findById();
}
}
If graduation is true i want to call Graduation class findById else i want to call Matriculation findById method .How can i achieve this in SpringBoot?
you can use the #ConditionalOnProperty annotation. Like this:
#ConditionalOnProperty(name = "graduation", havingValue = "true")
#Service
public class Graduation implements Student
{
#Override
public String findById()
{
return "Graduation";
}
}
correctly indicated in comments, here is a possible implementation.
class Test {
#Autowired
Matriculation matriculationStudent ;
#Autowired
Graduation graduationStudent;
#Value("${graduation}")
private boolean graduation;
void method(){
if (graduation) {
graduationStudent.findById();
} else {
matriculationStudent.findById();
}
}
}
You're gonna create a Spring Component like this:
#Component
public class StudentFactory {
#Autowired
private Matriculation matriculation;
#Autowired
private Graduation graduation;
#Value("${graduation}")
private boolean graduationValue;
public Student getImplementation() {
if (graduationValue) {
return graduation;
} else {
return matriculation;
}
}
}
and then you just inject the factory in the Test class and call getImplementation method
I can't manage to inject a property from application.yml to a spring data #Query.
The following results in an EL1008E error:
public interface MyRepository extends JpaRepository<MyEntity, Long> {
#Query("select e from MyEntity e where e.foo = :foo and e.env= ?#{env}")
MyEntity findByFoo(#Param("foo") String foo);
}
According to this blog it is possible to inject a property of spring's principal, which is not very different from what I would like to do.
Any hints on this?
I should really stop asking questions and answer them by myself shortly after ... That is not on purpose.
The mentioned blog has the solution included. Add this:
public class PropertyEvaluationContextExtension extends EvaluationContextExtensionSupport {
private final MyProps p;
public PropertyEvaluationContextExtension(final MyProps p) {
this.p= p;
}
#Override
public String getExtensionId() {
return "foo";
}
#Override
public MyProps getRootObject() {
return this.p;
}
}
#Configuration
public class PropertyConfig {
private final MyProps p;
public PropertyConfig(final MyProps p) {
this.p= p;
}
#Bean
EvaluationContextExtensionSupport propertyExtension() {
return new PropertyEvaluationContextExtension(p);
}
}
Now every property of MyProps is accessible via SpEL.
Best code practice for not duplicate your code in spring controller by abstract.
I've got two controllers for example
#Controller
public class DoSomethingController {
private Entity helpfulMethod(Form form) {
Entity e = new Entity();
return e;
}
#PostMapping("/something")
public String something(Form form){
helpfulMethod(form);
}
}
#Controller
public class DoSomethingElseController {
private Entity helpfulMethod(Form form) {
Entity e = new Entity();
return e;
}
#PostMapping("/somethingElse")
public String somethingElse(Form form){
helpfulMethod(form);
}
}
How to take helpfulMethod out and connect them from outside using abstract?
I guess you need to introduce a super class for both the controllers
public abstract class BaseDoSomethingController {
protected Entity helpfulMethod(Form form) {
Entity e = new Entity();
return e;
}
}
and let both your controllers inherit the base class
#Controller
public class DoSomethingController extends BaseDoSomethingController {
#PostMapping("/something")
public String something(Form form){
helpfulMethod(form);
}
}
and the same for the second controller
I have a doubt to use autowire annotation in different scenarios...
public Class A {
#Autowired
public B b;
public void print() {
System.out.println("the value is " + b.getValue());
}
}
Example 2:
public Class A {
public B b;
#Autowired
Public A(B b){}
public void print() {
System.out.println("the value is " + b.getValue());
}
}
The first method to autowire objects is called field-injection and the second one is called constructor-injection. There are many posts on SO about these two topics! E.g. What exactly is Field Injection and how to avoid it?
This should answer all of your questions.
public interface IFoo {}
public class Foo : IFoo {}
public sealed class NinjaModule : NinjectModule //Appropriately configured in project
{
public override void Load()
{
Bind<IFoo>.To<Foo>.InTransientScope();
}
}
public class SomeOtherClass : ISomeOtherInterface
{
public SomeOtherClass();
public IFoo GetFoo(IFoo foo)
{
return foo;
}
public void GetFoos()
{
foreach (var thing in everything)
{
var localFoo = GetFoo();
localFoo.UniqueProperty = "I am unique";
_fooList.Add(localFoo);
}
}
}
I need my code to look something like that.
Yes, I am fairly new to inject. I am fairly certain that I am missing a basic principle.
Thanks for any help.
I think the best approach here would be to use a factory to create the different Foo instances. And with Ninject and the Factory extension that's pretty easy.
public sealed class NinjaModule : NinjectModule //Appropriately configured in project
{
public override void Load()
{
Bind<IFoo>().To<Foo>().InTransientScope();
Bind<IFooFactory>().ToFactory();
}
}
public interface IFooFactory
{
IFoo CreateFoo();
}
public class SomeOtherClass : ISomeOtherInterface
{
private IFooFactory fooFactory;
public SomeOtherClass(IFooFactory fooFactory)
{
this.fooFactory = fooFactory;
}
public IFoo GetFoo(IFoo foo)
{
return this.fooFactory.CreateFoo();
}
public void GetFoos()
{
foreach (var thing in everything)
{
var localFoo = GetFoo();
localFoo.UniqueProperty = "I am unique";
_fooList.Add(localFoo);
}
}
}
This was a bad question. I figured out this needed to be implemented higher up by the class controlling these implementations.