Is there a way to store "extended enum" with JPA ?
I'm working with abstract object in my spring boot project and my base object can have multiple states. The object extending it can have the base state but also other specific states. You can't extend enum in Java, so my I first tought of using an interface with a default method isCommon to discriminate between my common enum values and my extended enum values in my services.
However I can't use the annotation #Enumerated on my property anymore. Is there a way to make it work or another pattern I could use ?
A small code sample to provide some context :
#Entity
abstract class AbstractFoo {
public StateInterface state;
}
#Entity
class ConcreteFoo extends AbstractFoo {
}
#Service
class ConcreteFooService {
public boolean isCommonState(ConcreteFoo foo) {
return foo.state.isCommon();
}
}
interface StateInterface {
default boolean isCommon() {
return false;
}
}
enum CommonState extends StateInterface {
BEGIN, END;
#Override
boolean isCommon() {
return true;
}
}
enum SpecificState extends StateInterface {
MIDDLE;
}
I would suggest you using the following Enum instead:
enum State {
BEGIN(true), MIDDLE(false), END(true);
private final boolean common;
State(boolean common) {
this.common = common;
}
public boolean isCommon() {
return common;
}
}
For your use case, this is the best I can think of.
Related
Problem Statement: I would like to create an annotation that behaves like an interface. The expectation is that any class that used this annotation should override the methods defined.
I would also like that a dynamic way to create instances based a name, ie: the annotated classes.
Something like
public #interface Food
{
public boolean isOrganic(String content);
}
#Food
class Potato {
public boolean isOrganic(String content)
{
....
return true;
}
}
#Food
class Tomato {
public boolean isOrganic(String content)
{
....
return false;
}
}
A subclass has a relationship that is described as IS-A with it base class, but a base class does not share this kind of relationship with it subclass. I was wandering what kind of relationship an interface have with it implementing class since an object of that class can be passed to interface object and the interface object can only access methods defined it concrete Interface.
public class main {
public static void main(String[]args){
Nigeria ng = new Nigeria(){};
//Interface object can accept Nigerias object which is not posible in Inheritance
Continent continent = ng;
//prints Country is in Africa
continent.Africa();
//continent.language(); will not compile language is not in the interface
//Print Democratic thought this should print Undefined since it is inialied with default.
continent.Goverment();
}
}
interface Continent{
public void Africa();
default void Goverment(){
System.out.println("Undefined");
}
}
class Nigeria implements Continent{
#Override
public void Africa(){
System.out.println("Country is in Africa");
}
public void language(){
System.out.println("Official Language is English");
}
public void Goverment(){
System.out.println("Democratic");
}
}
If you are looking for English-language analogues, an Interface is not an "Is a..." nor "Has a..." relationship, but more an "Is...".
An Interface is not about the class that uses it.
It's about the consumer that asks for it.
If you wanted to see it as anything, you could see it as an adjective.
"He is Responsible".
Well, what does he do?
He finishes tasks; he takes ownership of his mistakes; he makes them right.
Is he a pilot, is he a surgeon, is he a doctor?
Is he a child, a father, a greatGrandfather?
Do you care?
I need a responsible person, to help me do this job.
Does ResponsiblePerson inherit from PoliceOfficer? Does Lawyer inherit from ResponsiblePerson, because I'm sure there can be irresponsible lawyers.
class Lawyer extends Person { }
class ResponsibleLawyer extends Lawyer implements ResponsibleEntity { }
class NeedyPerson extends Person {
public void acceptHelp (ResponsibleEntity somebody) {
try {
somebody.attemptTask( someTask );
} catch (TaskCompletionError err) {
somebody.takeOwnership(err);
somebody.fixMistake(err);
}
}
}
Can corporations be Responsible too?
Perhaps we don't see it too often, but it's theoretically possible:
class LawFirm extends CorporateEntity { }
class BetterLawFirm extends LawFirm implements ResponsibleEntity { }
Can somebody be a responsible corporate body? Well, so long as that corporate body does all of the same things that the responsible person would otherwise do, sure.
In another example, you might have a Switchable interface.
Looking at that name, you could surmise that the thing you're being given has a switch which can be poked.
So what methods might it have?
on( )
off( )
toggle( )
isOn( )
sounds like a useful set to have.
What benefit is there to having an interface like this?
Well, now I know that I can deal with a switch, and its lineage doesn't matter.
If all I want is a class which takes a switch and does something with it, why do I need to create dozens of classes, just to accept my dozens of things with switches?
Or override methods into the dirt to do the same.
class SwitchThrower {
public void throwSwitch (CoffeeMaker coffeeMaker) { coffeeMaker.on(); }
public void throwSwitch (LightSwitch lightSwitch) { lightSwitch.on(); }
public void throwSwitch (GhostTrap ghostTrap) { ghostTrap.on(); }
public void throwSwitch (TheHeat theHeat) { theHeat.on(); }
public void throwSwitch (CarIgnition ignition) { ignition.on(); }
}
...
why not just:
class SwitchThrower {
public void throwSwitch (Switchable switch) { switch.on(); }
}
class LightSwitch implements Switchable {
private boolean currentlyOn;
public LightSwitch (boolean initiallyOn) {
currentlyOn = initiallyOn;
}
public LightSwitch () {
currentlyOn = false;
}
public boolean on () {
currentlyOn = true;
return currentlyOn;
}
public boolean off () {
currentlyOn = false;
return currentlyOn;
}
public boolean toggle (boolean forceOn) {
boolean state;
if (forceOn == true) {
state = on();
} else {
state = off();
}
return state;
}
public boolean toggle () {
boolean state;
if (isOn() == true) {
state = off();
} else {
state = on();
}
return state;
}
public boolean isOn () {
return currentlyOn;
}
}
...et cetera
As you can see, aside from describing a basic feature-set of the implementer, interfaces are not about the class at all, but rather the consumer.
An even more awesome implementation of this, in different languages, is _Traits_.
Traits are typically like Interfaces, but they have default behaviour associated with them.
Looking at my Switchable and my LightSwitch, you could imagine that practically all classes with this switch would have the same methods, with the same method behaviour...
...so why would I rewrite all of those methods over again, if I'm already going through the trouble of defining the signature in the interface?
Why couldn't I just add default behaviour in there, and have it apply to the implementer, unless a method is overridden?
Well, that's what Traits / Mix-Ins allow.
The relationship is only the "contract" that the class is getting to implement the methods the interface is offering.
That is how java can separate WHAT objects can do (Interface) and HOW the inherited class will do it.
I can't seem to figure out the best approach to tackle the following problem. Let's say there is an abstract base class with several concrete subclasses:
public abstract class AbstractType { /* common properties */ }
public class TypeA { /* properties of type A */ }
public class TypeB { /* properties of type A */ }`
These are domain classes (JPA entities). The properties of the types are (amongst other things) used to validate user data. I'm under the assumption that adding logic to the domain model itself is considered bad practice. Therefore, I want to avoid adding a validate method to the concrete subclasses. Like so:
UserInput userInput = ...;
AbstractType data = ...;
data.validate(userInput);
I don't see an option without having to cast the domain model,
if I want to move the logic to a logic layer. With the limited knowledge I have, I can only come up with following two similar "solutions", using some kind of handler interface.
Keep some explicit reference to the handler in the type
public interface TypeHandler {
public validate(AbstractType data, UserInput userInput);
}
/* TypeAHandler & TypeBHandler implementations */
public enum Type {
TYPE_A(new TypeAHandler()),
TYPE_B(new TypeBHandler());
private TypeHandler handler;
public Handler(TypeHandler handler){
this.handler = handler;
}
public TypeHandler getHandler(){ return handler; }
}
public class TypeA {
private Type type = TYPE_A;
/* ... */
}
The handler would than be called in the following manner:
UserInput userInput = ...;
AbstractType data = ...;
data.getType.getHandler().validate(data, userInput);
The reference to the handler could also be added immediately (without the enum in between) as property to the AbstractType class, but that would mean there is a reference to a class inside the logic layer from the domain model (which kind of defeats the purpose of moving the logic to a logic layer?)
The problem here too is that the validate method inside the TypeXHandler needs to cast the data argument to its subclass first before it can start validating.
Or I could implement some method which has a large if-then structure to get the right subclass, cast it and call the appropriate handler which implements an interface similar to the following.
public interface TypeHandler<T extends AbstractType> {
public validate(T data, UserInput userInput);
}
So in both cases there is casting. In the first case there is no huge if-then structure, but the logic and domain are not separated. In the second case there is a very inflexible if-then structure.
To conclude, here is my question. Should I really avoid implementing the logic directly inside the domain? If so, is there any way to avoid the casting, the if-else structure and/or adding additional properties to the domain model (like the enum in the first "solution").
At the end of the day, you're branching based on the subtype (concrete classes) since the logic to validate user input is based on those specific details contained in the subclasses.
Generics don't really help you much here since generics are based primarily on applying logic that is uniform across different types, operating on universal logic applied to a common interface that all applicable types share. Here your logic and interface varies for each subtype.
So your main choices are an inextensible solution where you're modifying central source code (like a big bunch of ifs/elses, a map, etc) and manually branching based on subtype, or using abstraction/dynamic polymorphism as an extensible solution which doesn't require modifying any central source code and automatically branches based on subtype.
Reflection might also be a possible route if you can afford it (it's a bit expensive at runtime) and provided it can fit to give you that universal logic you can implement centrally.
If you don't want to add this validate method to AbstractType and all of its subtypes, then you can always add another level of abstraction on top which does contain a validate method like ValidatorB which implements the IValidator interface and stores an object of TypeB as a member and applies the logic used to validate user input using TypeB's properties.
I studied design patterns last week and I would like to propose my solution (it works but I'm not sure that is the smartest way to resolve your problem).
The idea of my solution is to use a factory: you give a model (in your case a JPA entity) to the factory and it gives you the correct validator for that model.
At the beginning of the program, you have to tell to the factory which is the validator class for each model class of your program through a register method.
Let's start with the implementation...
AbstractModel.java
public abstract class AbstractModel
{
private final int commonProperty;
protected AbstractModel(int commonProperty)
{
this.commonProperty = commonProperty;
}
public int getCommonProperty() { return commonProperty; };
}
In the AbstractModel we put all the common properties of the models.
ModelA.java
public class ModelA extends AbstractModel
{
private final int specificProperty1;
private final int specificProperty2;
public ModelA(int commonProperty, int specificProperty1, int specificProperty2)
{
super(commonProperty);
this.specificProperty1 = specificProperty1;
this.specificProperty2 = specificProperty2;
}
public int getSpecificProperty1() { return specificProperty1; }
public int getSpecificProperty2() { return specificProperty2; }
}
ModelA has got two specific properties.
ModelB.java
public class ModelB extends AbstractModel
{
private final int specificProperty1;
private final int specificProperty2;
public ModelB(int commonProperty, int specificProperty1, int specificProperty2)
{
super(commonProperty);
this.specificProperty1 = specificProperty1;
this.specificProperty2 = specificProperty2;
}
public int getSpecificProperty1() { return specificProperty1; }
public int getSpecificProperty2() { return specificProperty2; }
}
ModelB has got two specific properties too.
Let's say that an instance a of ModelA is valid iff
a.commonProperties == a.specificProperty1 + a.specificProperty2
and an instance b of ModelB is valid iff
b.commonProperties == b.specificProperty1 * b.specificProperty2
Validator.java
public interface Validator
{
public boolean validate();
}
A really simple interface for the validators.
AbstractValidator.java
public abstract class AbstractValidator implements Validator
{
private final AbstractModel toBeValidated;
protected AbstractValidator(AbstractModel toBeValidated)
{
this.toBeValidated = toBeValidated;
}
protected AbstractModel getModel()
{
return toBeValidated;
}
}
This is the superclass of the concrete validators that wraps the model to be validated.
ValidatorA.java
public class ValidatorA extends AbstractValidator
{
protected ValidatorA(AbstractModel toBeValidated)
{
super(toBeValidated);
}
public boolean validate()
{
ModelA modelA = (ModelA) getModel();
return modelA.getCommonProperty() == modelA.getSpecificProperty1() + modelA.getSpecificProperty2();
}
}
The validator for the instances of ModelA.
ValidatorB
public class ValidatorB extends AbstractValidator
{
protected ValidatorB(AbstractModel toBeValidated)
{
super(toBeValidated);
}
public boolean validate()
{
ModelB modelB = (ModelB) getModel();
return modelB.getCommonProperty() == modelB.getSpecificProperty1() * modelB.getSpecificProperty2();
}
}
And this is the validator for the instances of ModelB.
And finally it comes the factory!
ValidatorFactory.java
public class ValidatorsFactory
{
private static ValidatorsFactory instance;
private final HashMap<Class<? extends AbstractModel>, Class<? extends Validator>> registeredValidators;
private ValidatorsFactory()
{
registeredValidators =
new HashMap<Class<? extends AbstractModel>, Class<? extends Validator>>();
}
public static ValidatorsFactory getInstance()
{
if (instance == null)
instance = new ValidatorsFactory();
return instance;
}
public void registerValidator(
Class<? extends AbstractModel> model,
Class<? extends Validator> modelValidator)
{
registeredValidators.put(model, modelValidator);
}
public Validator createValidator(AbstractModel model)
{
Class<? extends Validator> validatorClass = registeredValidators.get(model.getClass());
Constructor<? extends Validator> validatorConstructor = null;
Validator validator = null;
try
{
validatorConstructor = validatorClass.getDeclaredConstructor(new Class<?>[] { AbstractModel.class });
validator = (Validator) validatorConstructor.newInstance(new Object[] { model });
}
catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
System.err.println(e.getMessage());
// handle exception
}
return validator;
}
}
The factory is a singleton with two significant method:
registerValidator to add a new pair (modelClass, validatorClass) in the HashMap.
createValidator to obtain the correct validator for the specified model.
This is how to use this pattern:
public class Main
{
public static void main(String args[])
{
ValidatorsFactory factory = ValidatorsFactory.getInstance();
factory.registerValidator(ModelA.class, ValidatorA.class);
factory.registerValidator(ModelB.class, ValidatorB.class);
ModelA modelA = new ModelA(10, 4, 6);
if (factory.createValidator(modelA).validate())
System.out.println("modelA is valid");
else
System.out.println("modelA is not valid");
ModelB modelB = new ModelB(10, 8, 2);
if (factory.createValidator(modelB).validate())
System.out.println("modelB is valid");
else
System.out.println("modelB is not valid");
}
}
output:
modelA is valid [because 10 = 4 + 6]
modelB is not valid [because 10 != 8 * 2]
Note that the model is completely separeted from the controller and it uses only one cast from AbstractModel to a concrete model.
Hope it helps!
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)){
}
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.