I have an interface which multiple enums are implementing, i.e
public interface MinorCodes {
public abstract int code();
public abstract String description();
}
public enum IdentityMinorCodes implements MinorCodes {
IDENTITY_UPLOAD_PICTURE_CODE(1, "Error while trying to upload a picture."),
}
Now I want to have a custom annotation which has a value type of one of these concrete enum values, i.e
public #interface PokenService {
MinorCodes[] exceptions();
}
But of course I cannot return an interface here.
Does anyone know any solution or workaround to this?
Thanks in advance.
You could create an additional enum that wraps all your MinorCodes enum values:
public enum MinorCodesWrapper {
IDENTITY_UPLOAD_PICTURE_CODE(IdentityMinorCodes.IDENTITY_UPLOAD_PICTURE_CODE),
SOME_CODE(AnotherMinorCodes.SOME_CODE);
private final MinorCodes _wrapped;
MinorCodesWrapper(MinorCodes wrapped) {
_wrapped = wrapped;
}
public MinorCodes getWrapped() {
return _wrapped;
}
}
public #interface PokenService {
MinorCodesWrapper[] exceptions();
}
Not pretty, but works ;)
Related
Best way to implement factory pattern in Spring boot.
I've an interface and multiple implementations of it. During a request, I need to return the bean based on an input string.
There are multiple ways I can do it.. But whats the best way?
interface vehicle {
void drive();
string getVehicleName();
}
#Component
public class Car implements vehicle {
private static string prop = "car";
#Override
string getVehicleName() { return prop;}
#Override
void drive() {}
}
#Component
public class Bike implements vehicle {
private static string prop = "bike";
#Override
string getVehicleName() { return prop;}
#Override
void drive() {}
}
#Service
public class VehicleFactory {
#Autowired
private List<vehicle> vehicles;
private static final HashMap<String, vehicle> requestVehicleMap = new HashMap<>();
#PostConstruct
public void initVehicleFactory() {
for(vehicle vehicle : vehicles) {
requestVehicleMap.put(vehicle.getVehicleName(), request);
}
}
public static vehicle getVehicleImpl(String vehicleName) {
return requestVehicleMap.get(vehicleName);
}
}
This does give me correct class.
Also there is "qualifier" that can be used as Implementing custom factory pattern in Spring.
But is there better approach?
Interface and it's Implementation are good, I would just change the Factory class alone because you already I got the List of Implementation then Why again to initialise it in a Map
I will also comment the suggestions in the code
VehicleFactory
#Service
public class VehicleFactory {
#Autowired
private List<Vehicle> vehicles;
public Vehicle getVehicleImpl(String vehicleName) { // You have already declared as #Service then why use static
return vehicles.stream()
.filter(vehicle -> vehicle.getVehicleName().equalsIgnoreCase(vehicleName)) // This will filter the Impl you needed from others
.findFirst()
.orElseThrow(() -> new RuntimeException(String.format(" Invlaid Vehicle Name - %s", vehicleName))); // Incase Impl is not found it should throw an error or handle in some other ways
}
}
So give it a try
I have a utility class OldRemote which has been deprecated now, but still it will be used for a while till the new class NewRemote is stable. And both the utility classes has the same method names and parameters, But the return type pojo classes are different. Even return type pojo structure is same, but naming is different.
In simple, both the function return types are pojo's with different field names.
Is there any generic way to handle this below usecase ?
I have created a service interface which has the generic method contract of both old and new class.
public interface RemoteService {
//contract [ return type is object to receive all/any Pojo classes ]
Object turnOnTV();
static Service GetRemoteservice(boolean isOldRemote){
if(isOldRemote){
return new OldRemote();
}
return new NewRemote();
}
}
OldRemote Class
public class OldRemote implements RemoteService{
#Override
public OldPojo turnOnTV() {
OldPojo oldPojo = new OldPojo();
System.out.println("OldPojo");
return oldPojo;
}
}
NewRemote Class
public class NewRemote implements Service{
#Override
public NewPojo turnOnTV() {
NewPojo newPojo = new NewPojo();
System.out.println("NewPojo");
return newPojo;
}
}
Demo usage of above implementation.
public class DemoTvRemote {
public static void main(String[] args) {
RemoteService remoteService1 = RemoteService.GetRemoteservice(true);
OldPojo oldRemote = (OldPojo) remoteService1.turnOnTV();
RemoteService remoteService2 = RemoteService.GetRemoteservice(false);
NewPojo shr = (NewPojo) Service2.test();
}
}
This above code works fine. But the problem is I don't want to type cast in all the places where turnOnTV() is used in my entire code base. Even If I have to do that, I will have to write a condition to switch between OldPojo and NewPojo where ever the turnOnTV() is invoked.
Is there any way to solve this problem ?
You could create a base class or interface they both extend/implement.
public abstract class RemoteServiceBase<E> {
public abstract E turnOnTv();
}
public class NewRemoteService extends RemoteServiceBase<NewRemotePojo >{
public NewRemotePojo turnOnTv() {
return new NewRemotePojo();
}
}
public class OldRemoteService extends RemoteServiceBase<OldRemotePojo >{
public OldRemotePojo turnOnTv() {
return new OldRemotePojo();
}
}
This would still only work if you know the service type. Otherwise you work with the common generic type as one would expect.
We can deal with this with the following approach :
1) We can create a dummy POJO class in a common location with having the reference of both OldPojo and NewPojo as data members
public class CommonPojo {
OldPojo oldPojo;
NewPojo newPojo;
public void setOldPojo(OldPojo oldPojo){
this.oldPojo=oldPojo;
}
public void setNewPojo(NewPojo newPojo){
this.newPojo=newPojo;
}
public OldPojo getOldPojo(){
return oldPojo;
}
public NewPojo getNewPojo(){
return newPojo;
}
}
2)We can write a Utility method as follow which can give an object of commonpojo :
public class CommonRemote {
public static CommonPojo turnOnTv(Boolean isOldRemote){
CommonPojo commonPojo = new CommonPojo
if(isOldRemote){
OldPojo oldPojo =new OldPojo();
commonPojo.setOldPojo(oldPojo);
}else{
NewPojo newPojo =new NewPojo();
commonPojo.setNewPojo (newPojo);
}
}
}
3) Use this method as turnOnTv() as Follows :
public class DemoTvRemote {
public static void main(String[] args) {
CommonPojo remote1 = CommonRemote.turnOnTv(true);
OldPojo oldRemote = remote1.getOldPojo();
CommonPojo remote2 = CommonRemote.turnOnTv(false);
NewPojo newRemote = remote2.getNewPojo();
}
}
with this approach with little changes in code We can achieve your requirement without any typecasting.
How to choose CDI java bean base on annotation, then the annotation poses table of arguments?
The problem is easier to show using an example than to describe.
Assume that for each object of type Problem we have to choose proper solution.
public class Problem {
private Object data;
private ProblemType type;
public Object getData() { return data; }
public void setData(Object data) { this.data = data; }
public ProblemType getType() { return type; }
public void setType(ProblemType type) { this.type = type;}
}
There are few types of problems:
public enum ProblemType {
A, B, C;
}
There are few solutions:
public interface Solution {
public void resolve(Problem problem);
}
like FirstSolution:
#RequestScoped
#SolutionQualifier(problemTypes = { ProblemType.A, ProblemType.C })
public class FirstSolution implements Solution {
#Override
public void resolve(Problem problem) {
// ...
}
}
and SecondSolution:
#RequestScoped
#SolutionQualifier(problemTypes = { ProblemType.B })
public class SecondSolution implements Solution {
#Override
public void resolve(Problem problem) {
// ...
}
}
The solution should be chosen based on annotation #SolutionQualifier:
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface SolutionQualifier {
ProblemType[] problemTypes();
public static class SolutionQualifierLiteral extends AnnotationLiteral<SolutionQualifier> implements SolutionQualifier {
private ProblemType[] problemTypes;
public SolutionQualifierLiteral(ProblemType[] problems) {
this.problemTypes = problems;
}
#Override
public ProblemType[] problemTypes() {
return problemTypes;
}
}
}
By SolutionProvider:
#RequestScoped
public class DefaultSolutionProvider implements SolutionProvider {
#Inject
#Any
private Instance<Solution> solutions;
#Override
public Instance<Solution> getSolution(Problem problem) {
/**
* Here is the problem of choosing proper solution.
* I do not know how method {#link javax.enterprise.inject.Instance#select(Annotation...)}
* works, and how it compares annotations, so I do no know what argument I should put there
* to obtain proper solution.
*/
ProblemType[] problemTypes = { problem.getType() };
return solutions.select(new SolutionQualifier.SolutionQualifierLiteral(problemTypes));
}
}
And in the last one there is a problem:
I do not know how method javax.enterprise.inject.Instance#select(Annotation...) works internally, and how it compares annotations, so I do no know what argument I should put there to obtain proper solution. If there appear a problem of type A table ProblemType[] will consist of one argument, while FirstSolution.class is annotated with #SolutionQualifier having two arguments, so therefore I will not get the proper Instance.
I didn't find a way to resolve it using CDI API, instead:
I created another enum:
public enum SoultionType {
A(ProblemType.A, ProblemType.C),
B(ProblemType.A);
//...
SoultionType(ProblemType problems...) {
// ...
}
public static SoultionType getByProblemType(ProblemType problem) {
// ...
}
}
Changed so SolutionQualifier has only SoultionType field inside, so there is no problem with the comparison.
How to pass enum in enum constructor ?
Here is what I tried so far.
This is to guarantee that I don't mix up pages and their respective sections.
I would like to be able to do 'SectionsEnum section = PAGE2.sectionsEnum.SECTION_D;' somewhere else in my code.
PagesEnum.class
public enum PagesEnum {
PAGE1(Page1Sections.class), // incompatible types, required SectionsEnum found Page1Sections
PAGE2(Page2Sections.class);
Class<? extends SectionsEnum> sectionsEnum;
PagesEnum(final Class<? extends SectionsEnum> sectionsEnum) {
this.sectionsEnum = sectionsEnum;
}
}
Page1Sections.enum
public enum Page1Sections implements SectionsEnum {
SECTION_A,
SECTION_B;
}
Page2Sections.enum
public enum Page2Sections implements SectionsEnum {
SECTION_C,
SECTION_D;
}
Main.class
public class Main {
public void example() {
SectionsEnum section = PAGE2.sectionsEnum.SECTION_D;
}
}
you can never get PAGE2.SECTION_D but you can do the relation other way around SECTION_D.getPage():
:
public enum SectionsEnum {
SECTION_A(PagesEnum.PAGE1),
SECTION_B(PagesEnum.PAGE1),
SECTION_C(PagesEnum.PAGE2),
SECTION_D(PagesEnum.PAGE2),
;
PagesEnum(PagesEnum page) {...}
}
For example, for a game I have some Skill, which is data object:
public interface Skill{
public String getName();
}
public class Attack implements Skill{
public String getName(){ return "Attack"; }
public int power;
}
public class Speak implements Skill{
public String getName(){ return "Speak"; }
public String speech;
}
To apply the skills during the game, I need some SkillHandler for each corresponding skill:
public interface SkillHandler{
public void apply(Skill skill);
}
public class AttackHandler{
#Override
public void apply(Skill skill){
Attack attack=(Attack)skill;
Player player=Global.getPlayer();
Enemy enemy=Global.getEnemy();
enemy.hp=enemy.hp-attack.power;
//some other code for follow up handle
}
}
public class SpeakHandler{
#Override
public void apply(Skill skill){
Speak speak=(Speak)skill;
Label label=new Label(speech);
this.displayOnTop(label);
}
}
I use one SkillHandler for each Skill because I don't want the Skill depend on SkillHandler, and PlayerAttackStateHandler would apply each skill:
public class PlayerAttackStateHandler{
public PlayerAttackHandler(){
Skill[] skills=Global.getSkills();
for(int i=0;i<skills.length;i++){
SkillHandler skillHandler=null;
if(skills[i].getName().equals("Attack")){
skillHandler=new AttackHandler();
}else if(skills[i].getName().equals("Speak")){
skillHandler=new SpeakHandler();
}
skillHandler.apply(skills[i]);
}
}
}
I know this design is ill-formed because it has at least 2 problems:
I need to update the long if-else chain if a new Skill as well as new SkillHandler is added, which seems does't follow open-closed principle
it has a dynamic cast in each SkillHandler
My question is, is there any design pattern to eliminate both if-else and dynamic cast (if possible) in this case, while keep the Skill not depend on SkillHandler?
It seems that your implementation has lot in common with visitor pattern, something like this:
public interface ISkillable //this is your Skill
{
public int GetPower();
public string GetSpeak();
}
public interface IVisitable //player or npc
{
public void Accept(IVisitor visitor)
}
public interface IVisitor //AttackHandler or SpeakHandler
{
public void ApplySkill(ISkillable skillable)
}
public class Player implements ISkillable, IVisitable
{
...
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
public class AttackVisitor implements IVisitor
{
public void Visit(ISkillable skillable)
{
//do something with power
}
}
and then example how it can be used is
player.Accept(new AttackVisitor(/*you can provide additional info like enemy*/));
player.Accept(new SpeakVisitor());
See Attack and Speak as capabilities some agent could possess.
I would consider testing capabilities/features:
interface Attacking { void attack(); }
interface Speaking { void speak(); }
Animal animal = ...
Optional<Attacking> attacker = animal.lookup(Attacking.class);
attacker.ifPresent(a -> a.attack());
Optional<Speaking> speaker = animal.lookup(Speaking.class);
speaker.ifPresent(sp -> sp.speak());
Animal need not implement any interface, but you can look up (lookup or maybe as) capabilities. This is extendible in the future, dynamic: can change at run-time.
Implementation as
private Map<Class<?>, ?> map = new HashMap<>();
public <T> Optional<T> lookup(Class<T> type) {
Object instance = map.get(type);
if (instance == null) {
return Optional.empty();
}
return Optional.of(type.cast(instance));
}
<S> void register(Class<S> type, S instance) {
map.put(type, instance);
}
The implementation does a safe dynamic cast, as register ensures the safe filling of (key, value) entries.