I've a base class with a property that should be set in the derived class. I've to use annotations. How's that possible?
I know how do this with xml spring configurations, but not with annotations, because I've to write them at the property?
Here's some example code:
public class Base {
// This property should be set
private String ultimateProperty;
// ....
}
public class Hi extends Base {
// ultimate property should be "Hi" in this class
// ...
}
public class Bye extends Base {
// ultimate property should be "Bye" in this class
// ...
}
How is this possible with annotations?
Some options depending on what else Base has:
class Base {
private String ultimateProperty;
Base() {
}
Base(String ultimateProperty) {
this.ultimateProperty = ultimateProperty;
}
public void setUltimateProperty(String ultimateProperty) {
this.ultimateProperty = ultimateProperty;
}
}
class Hi extends Base {
#Value("Hi")
public void setUltimateProperty(String ultimateProperty) {
super.setUltimateProperty(ultimateProperty);
}
}
class Bye extends Base {
public Bye(#Value("Bye") String ultimateProperty) {
setUltimateProperty(ultimateProperty);
}
}
class Later extends Base {
public Later(#Value("Later") String ultimateProperty) {
super(ultimateProperty);
}
}
class AndAgain extends Base {
#Value("AndAgain")
private String notQuiteUltimate;
#PostConstruct
public void doStuff() {
super.setUltimateProperty(notQuiteUltimate);
}
}
Of course, if you really just want the name of the class there, then
class SmarterBase {
private String ultimateProperty = getClass().getSimpleName();
}
Annotations for fields are linked directly to the source code in the class. You may be able to do what you are looking for via Spring EL with-in an #Value annotation, but I think the complexity overrides the value.
A pattern you may want to consider is using #Configuration annotation to programmatically setup your application context. That way you can define what is injected into the base class.
Related
I have a highly specific question. I am using Spring boot with Java. Suppose I have a Verifier interface which has a verify method. Suppose I have 3 concrete implementations of this say VerifierA, VerifierB, VerifierC. If I have a VerificationService class where these 3 verifiers are being injected, Is there any way by which I can access all these verifiers inside a method of VerificationService class?
The code is as given below
public Interface Verifier {
public void verify(Obj obj);
}
#Component
public class VerifierA implements Verifier{
#Override public void verify(Obj obj) {
// do somethingA
}
}
#Component
public class VerifierB implements Verifier{
#Override public void verify(Obj obj) {
// do somethingB
}
}
#Component
public class VerifierC implements Verifier{
#Override public void verify(Obj obj) {
// do somethingC
}
}
#Service
public VerificationService() {
#Autowired private final Verifier verifierA;
#Autowired private final Verifier verifierB;
#Autowired private final Verifier verifierC;
public void test(Obj obj) {
//here I want to call verify method of all the 3 verifiers without explicitly calling all verifiers by variable names
//i want to do something like following
for(Verifier verifier: listOfInjectedVerifiers) {
verifier.verify(obj);
}
// the above is not working code. This is the behaviour I want
}
}
Is there any way to do this? Thanks in advance
Spring can inject all beans that implement an interface. To do so, declare that your component accepts a List of that interface type. Using constructor injection, that would look like this (untested pseudo-code):
#Service
public class VerificationService {
private List<Verifier> verifiers;
public VerificationService(List<Verifier> verifiers) {
this.verifiers = verifiers;
}
public void verify(Object object) {
for (Verifier verifier : verifiers) {
verifier.verify(object);
}
}
}
I have the following scenario:
#Component
#Scope("prototype")
public abstract class AbstractA {
protected abstract String getData();
}
Now I will require to create instances of this class in a dynamic manner (using anonymous inner classes). Such as:
#Component
public class B {
public void some_method() {
//Obviously this is wrong, I want to be able to do this through Spring/beans.
new AbstractA() {
protected abstract String getData() {
return "abc";
}
}
}
}
How would I be able to get instrances of the prototype bean in such scenario?
I am using Dagger 2 for the dependency management of my Java application.
I have the following structure:
public interface SecondaryService
{
void doSomethingElse(String data);
}
public class SecondaryServiceFirstImpl implements SecondaryService
{
public void doSomethingElse(String data)
{
// Do something else
}
}
public class SecondaryServiceSecondImpl implements SecondaryService
{
public void doSomethingElse(String data)
{
// Do something else
}
}
public interface MainInterface
{
void doSomething(String data);
}
public class MainService implements MainInterface
{
private SecondaryService secondaryService;
private DatabaseService databaseService;
public MainService(SecondaryService secondaryService, DatabaseService databaseService)
{
this.secondaryService = secondaryService;
this.databaseService = databaseService;
}
public void doSomething(String data)
{
String name = databaseService.getName(data);
// Resolve the NAMED SecondaryService based on the name property and
// use the implementation.
}
}
And here is the Dagger Module code:
#Module
public class DependencyRegisterModule
{
#Provides #Named('first')
SecondaryService provideSecondaryServiceFirstImpl ()
{
return new SecondaryServiceFirstImpl ();
}
#Provides #Named('second')
SecondaryService provideSecondaryServiceSecondImpl ()
{
return new SecondaryServiceSecondImpl ();
}
#Provides
DatabaseService provideDatabaseService ()
{
return new DatabaseServiceImpl();
}
#Provides
MainInterface provideMainInterface(SecondaryService secondaryService, DatabaseService databaseService)
{
return new MainService (secondaryService, );
}
}
As you can see I have a SecondaryService interface that is implemented by two classes. I want to resolve the named dependency for the SecondaryService based on a parameter, that I get from the database inside a method in the MainService.
Is there a way to do this? If this does not work with a Named dependencies, is there another way to do this?
So far I have used a factory pattern, but it is very hard to manage, as I have to pass the dependencies of the classes inside their constructor.
#Named—or #Qualifiers in general—are intended to be used if you need 2 objects of the same kind, e.g. injecting a String username and String email. In this case a qualifier could be used to distinguish between those objects.
In your case it seems that you want either one object or the other. In your case you should use different modules if you want to take a clean approach, or add an if/else to your module in the constructor.
Use a base class
#Module
public abstract class ServiceModule {
#Provides
public abstract SecondaryService providesServcie();
}
Then just create 2 sub classes of this module and provide the needed service respectively.
When creating your component just supply the right implementation of your module
if(1 == 1)
new MyComponent.Builder().add(new OneServiceModule()).build();
else
new MyComponent.Builder().add(new OtherServiceModule()).build();
And remember, you don't have to duplicate your other #Provides methods, since you can just use multiple modules with the component.
Use an if/else construct
#Module
public class DependencyRegisterModule
{
private int whichModule;
public DependencyRegisterModule(int whichModule) {
this.whichModule = whichModule;
}
#Provides
SecondaryService provideSecondaryServiceSecondImpl ()
{
return whichModule == 1 ? new SecondaryServiceSecondImpl() : new SecondaryServiceFirstImpl();
}
}
I hope I don't have to explain how if/else works ;)
I am currently working on designing some system where I'm confused if it will be right to control base class attributes with derived class.
For example:
Class Building {
String name;
String[] facilities;
}
Class OfficeBuilding extends Building{
}
Class ResidentialBuilding extends Building {
}
//Type of Building control attribute like facilities here which is empty by default. Should it be part of Derived classes or it should remain part of Base class and derived classes should just override its values ?
Things to keep in mind:
1). All classes are data classes here.
2). Base class facilities attribute is always empty and controlled by child class.
Thanks.
There is more than one solution. Not knowing your use case I would say name and facilities can be fully managed by parent class, not even directly accessible from child classes (only via constructor / some methods). I would also store facilities as list:
Class Building {
private String name;
private List<String> facilities;
public Building(String name, String... facilities) { // facilities won't be null this way
this.name = name;
this.facilities = new ArrayList<String>(Arrays.asList(facilities));
}
public Building(String name) {
this(name, new String[0]);
}
// Only if this makes sense
public Building() {
this("");
}
public String[] getFacilities() {
return facilities.toArray(new String[facilities.size()]);
}
// if needed you can...
public void addFacility(String facility) { ... }
public void removeFacility(String facility) { ... }
}
Class OfficeBuilding extends Building {
public OfficeBuilding() {
super("Office", "facility1", "facility2");
//...
}
}
public void test(Object obj){
//Here i have to set the values of the obj using its setter .
}
Test can be invoked with two objects as parameter. EG: test(standalone) and test(webapp), where standalone and webapp are beans.
public class standalone{
int version;
//setter and getter
}
public class Webapp{
String version;
//setter and getter
}
This test method has to set the values accordin to the parameter object.
Eg: IF i pass standalone as param. standalone's setter method shd be called. How to achieve this?
Note : Without using interface. How to do this?
Thanks.
public static void setVersion(Object obj, int v) throws Exception {
for (Method m : obj.getClass().getMethods()) {
final Class<?>[] t = m.getParameterTypes();
if (m.getName().equals("setVersion") && t.length == 1)
m.invoke(obj, t[0] == String.class? String.valueOf(v) : v);
break;
}
}
You could make both StandAlone and WebApp implement an interface, eg
interface VersionSettable {
void setVersion(int version);
}
public class Standalone implements VersionSettable{
int version;
//setter and getter
}
public class Webapp implements VersionSettable{
int version;
//setter and getter
}
public void test(VersionSettable versionSettable){
versionSettable.setVersion(42);
}
In the simpliest way you could do like this:
public void test(Object obj) {
if( obj instanceof Standalone ) {
((Standalone)obj).setVersion(1);
} else if (obj instanceof WebApp ) {
((WebApp)obj).setVersion(1);
}
}
Try to avoid use of reflection to achieve this because it will make refactoring tasks really hard. The same would be applied to compare the class name with a string.
If you want something more elegant you could do something like this:
public class abstract AbstractEnv {
int version = 0;
// setters and getters
}
public class Standalone extends AbstractEnv{
}
public class Webapp extends AbstractEnv{
}
with this approach you can configure it like this:
public void test(AbstractEnv obj) {
obj.setVersion(1);
}
Both of your classes should implement an interface like VersionSettable. Which declares the method setVersion(int version).
public class standalone implements VersionSettable {
int version;
//setter and getter
}
public class Webapp implements VersionSettable {
int version;
//setter and getter
}
interface VersionSettable {
setVersion(int version);
}
Then you can change your test method to this:
public void test(VersionSettable obj){
obj.setVersion(17);
}
I think would be best if you use inheritance in this case, because (as far as I can get it)
both Standalone and WebApp are Applications.
So you can define a top class "Application" and both StandaloneApp and WebApp extend it, because an "is a" relationship could be defined.
Skeleton code:
define class Application
define class StandaloneApp extends Application, implements method setVersion(int)
define class WebApp extends Application, implements method setVersion(int)
define test method, which accepts "Application" obj in the arguments
Also you can apply any of the interface solutions, presented above.
You can simply do this:
interface SetVersion{
void setVersion(int version);
}
class Standalone implements SetVersion{}
class WebApp implements SetVersion{}
public void test(SetVersion version){
version.setVersion(1);
}
Or the simplest way would be to use .instanceOf
if(obj.instanceOf(Standalone)){
}