I want to implement the state design pattern in JPA. The way I am currently doing this is outlined in this blog post.
The author uses an enum containing all available state implementations instead of creating abstract class/interface for state abstraction and writing implementation for each state. I find this approach very useful, since enums can be easily serialized in JPA and you can store the current state of your object without additional effort. I also nested the state interface and all state classes into the enum making them private, since they are implementation specific and should not be visible to any client. Here's a code example of the enum:
public enum State {
STATE_A(new StateA()),
STATE_B(new StateB());
private final StateTransition state;
private State(StateTransition state) {
this.state = state;
}
void transitionA(Context ctx) {
state.transitionA(ctx);
}
void transitionB(Context ctx) {
state.transitionB(ctx);
}
private interface StateTransition {
void transitionA(Context ctx);
void transitionB(Context ctx);
}
private static class StateA implements StateTransition {
#Override
public void transitionA(Context ctx) {
// do something
ctx.setState(STATE_B);
}
#Override
public void transitionB(Context ctx) {
// do something
ctx.setState(STATE_A);
}
}
private static class StateB implements StateTransition {
#Override
public void transitionA(Context ctx) {
throw new IllegalStateException("transition not allowed");
}
#Override
public void transitionB(Context ctx) {
// do something
ctx.setState(STATE_A);
}
}
}
I'd like to and share this with you and get your thoughts on it. Do you find this useful? How would you implement the state design pattern in a JPA domain model?
Well it's an old question, but for the sake of those who might search archives - I have used spring state machine with enums (instead Strings).
Regarding handling transitions, there are annotations that allow your functions to be called when transition happens.
1.1.0.RELEASE gives a default mechanism to persist a state by persisting StateMachineContext, and an alternative using persist recipe.
Now refering to JPA - it's possible to have Entity Listener that will initialize statemachine on postload (#Postload), I think it's not good path to go.
As a corollary this AspectJ pattern combined with constant-specific Enum classes is also useful. I am not showing Spring integration here as this focuses only on AspectJ. But I guess we can use Spring with AspectJ too.
One more point is that OO patterns can be powerful for this usecase. I show this pattern only because the question points to the blog post which has a link to a Spring and AspectJ example.
And I also have a need to use good OO patterns with JPA.
public interface StateTransition {
StateTransition activate();
StateTransition deActivate();
}
public enum AStateTransition implements StateTransition{
ACTIVATE(new Activation()),
DEACTIVATE(new DeActivation());
private final StateTransition stateTransition;
private AStateTransition(StateTransition stateTransition) {
this.stateTransition = stateTransition;
}
#Override
public StateTransition activate() {
return stateTransition.activate();
}
#Override
public StateTransition deActivate() {
return stateTransition.deActivate();
}
}
public class Activation implements StateTransition {
#Override
public StateTransition activate() {
return AStateTransition.ACTIVATE;
}
#Override
public StateTransition deActivate() {
return AStateTransition.DEACTIVATE;
}
}
public class DeActivation implements StateTransition {
#Override
public StateTransition deActivate() {
return AStateTransition.DEACTIVATE;
}
#Override
public StateTransition activate() {
return AStateTransition.ACTIVATE;
}
}
#Aspect()
public class StateChangeAspect {
//Could be more generic so that all implemented methods
//are covered
#Pointcut("execution(* AStateTransition.activate()) && target(stateTransition) && if()")
public static boolean stateChangePointcut( AStateTransition stateTransition ){
return AStateTransition.ACTIVATE == stateTransition;
}
#Before("stateChangePointcut(stateTransition)")
public void test1( AStateTransition stateTransition ) {
System.out.println( " aspect " );
}
#Before("stateChangePointcut(stateTransition)")
public void test1(JoinPoint joinPoint, AStateTransition stateTransition) {
System.out.println(joinPoint + " -> " + stateTransition);
}
}
Test code :
System.out.println(AStateTransition.ACTIVATE.activate());
System.out.println(AStateTransition.DEACTIVATE.deActivate());
Related
I have an application that takes json objects from a queue, deserializes them to a model, applies a list of filters, and sends the objects that pass all filters through to another queue.
The two complicating criteria are:
The set of filters is determined and injected via Spring profile at startup.
The type of object that the json is being deserialized to is also determined the by the Spring profile at startup.
The following solution is ugly because it involves casting:
public class MessageTypeOne {
public int someField;
}
public class MessageTypeTwo {
public int otherField;
}
public interface MessageFilter {
boolean doesFilterPass(Object object);
}
#Component
#Profile("ProfileOne")
public class OneOfMyMessageFilters implements MessageFilter {
public boolean doesFilterPass(Object object) {
MessageTypeOne message = (MessageTypeOne)object;
if (message.someField == something) {
return false;
} else return true;
}
}
#Component
#Profile("ProfileTwo")
public class AnotherOneOfMyMessageFilters implements MessageFilter {
public boolean doesFilterPass(Object object) {
MessageTypeTwo message = (MessageTypeTwo)object;
if (message.otherField == something) {
return false;
} else return true;
}
}
#Service
public class MessageFilterService {
// injected at runtime via Spring profile
private Set<MessageFilter> messageFilters
#AutoWired
public MessageFilterService(Set<MessageFilter> messageFilters) {
this.messageFilters = messageFilters;
}
public boolean passesAllFilters(Object object) throws IOException {
for (MessageFilter filter : messageFilters) {
if (!filter.doesFilterPass(object)) {
return false;
}
}
return true;
}
}
What's the cleanest pattern for cases like these? I've read about the visitor pattern but I'm not sure that's any better than casting like this.
As far as design pattern is concerned, I think it is of type Strategy pattern. I am not talking about Spring way of implementation. You may have n number of filters, but you have to choose based upon the context. So strategy pattern is best fitted here. Others can provide other patterns. You can strategy pattern in the below link.
https://en.wikipedia.org/wiki/Strategy_pattern
What about visitor pattern with Java reflection? Here is an old article:
https://www.javaworld.com/article/2077602/java-tip-98--reflect-on-the-visitor-design-pattern.html
When you want to decouple messages from filters and relation is many to many you can always use Chain of Responsibility.
#Service
public class MessageFiltersAggregator {
private MessageFilter chainEntryNode;
#AutoWired
public MessageFilterService(Set<MessageFilter> messageFilters) {
this.chainEntryNode = buildChain(messageFilters);
}
public boolean passesAllFilters(Object object) throws IOException {
return chainEntryNode.doesFilterPass(object);
}
}
You need to implement buildChain method which creates chain from collection. Of course, each element in chain should have next property. In this case MessageFilter could look like below:
public abstract class MessageFilter {
private MessageFilter next;
//constructors, setters, etc
public boolean doesFilterPass(Object object) {
boolean res = true;
if (canHandle(object)) {
res = validate(object);
}
return res && next.doesFilterPass(object);
}
public abstract boolean validate(Object object);
public abstract boolean canHandle(Object object);
}
Abstract class contains chain logic you just need to implement two methods in each subclass. One of implementation could look like below:
public class AnotherOneOfMyMessageFilters extends MessageFilter {
public boolean canHandle(Object object) {
return object instanceof MessageTypeTwo;
}
public boolean validate(Object object) {
MessageTypeTwo message = (MessageTypeTwo)object;
return message.otherField == something;
}
}
All above classes are just example created without IDE so could have issues in syntax but should give you an idea how it should work.
See also:
Chain of Responsibility in Java
Chain of Responsibility Design Pattern in Java
If I understand your problem correctly, then it's possible to configure your Spring profile in a way that makes your filters throw ClassCastExceptions.
Assuming that you configuration options are the way you want, then it demonstrates the only real problem with your design -- your filters can be applied to any Object, and that's what the interface says -- doesFilterPass( Object ) -- but your filters only really work with certain types of objects.
That's what you need to fix. If the filter is applied to a strange type of object, does it pass or fail? You can decide this on a per-filter basis and then just fix it like this:
public boolean doesFilterPass(Object object) {
if (!(object instanceOf MessageTypeTwo)) {
return true;
}
MessageTypeTwo message = (MessageTypeTwo)object;
if (message.otherField == something) {
return false;
} else return true;
}
Easy peasy.
I know you don't like the cast, but it's a direct result of the configuration options you provide -- the profile can be configured to apply filters to any kind of object. You just need to support that, and that means there has to be casting somewhere.
This became much cleaner with generics. Since I know what type of Object each filter can handle I can just do this, eliminating the casting:
public class MessageTypeOne {
public int someField;
}
public class MessageTypeTwo {
public int otherField;
}
public interface MessageFilter<T> {
boolean doesFilterPass(T message);
}
#Component
#Profile("ProfileOne")
public class OneOfMyMessageFilters<T extends MessageTypeOne> implements MessageFilter<T> {
public boolean doesFilterPass(MessageTypeOne message) {
if (message.someField == something) {
return false;
} else return true;
}
}
#Component
#Profile("ProfileTwo")
public class AnotherOneOfMyMessageFilters<T extends MessageTypeTwo> implements MessageFilter<T> {
public boolean doesFilterPass(MessageTypeTwo message) {
if (message.otherField == something) {
return false;
} else return true;
}
}
#Service
public class MessageFilterServiceImpl<T> implements MessageFilterService<T> {
// injected at runtime via Spring profile
private Set<MessageFilter<T>> messageFilters
#AutoWired
public MessageFilterService(Set<MessageFilter<T>> messageFilters) {
this.messageFilters = messageFilters;
}
public boolean passesAllFilters(T message) throws IOException {
for (MessageFilter filter : messageFilters) {
if (!filter.doesFilterPass(message)) {
return false;
}
}
return true;
}
}
public interface MessageFilterService<T> {
boolean passesAllFilters(T rawEvent) throws IllegalArgumentException;
}
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.
i'm developing an android app using MVP pattern.
I'd like to have different presenters, and each one implements getItems, that call a getAll static method of the associated model.
I thought to use generics, ended up like this:
public class BasePresenter<T> {
protected T mModel;
List getItems() {
mModel.getAll();
}
}
public class Presenter extends BasePresenter<Model> {
}
but i cannot access getAll methods using generics, because is not an Object's method.
Since for me would be dumb to write the same boring method getAll() for all presenter, changing only the model, is there there any way to accomplish that?
I'm asking because even in Google's official MVP guide, it use always the same method to retrive data, overriding it on each presenter, and i'm hoping that there is a better way.
I thought to "cast" the superclass mModel, but i don't know how and if it's possible to do, though.
Try this
public class BasePresenter<M extends BaseModel<M>> {
#Nullable
private M mModel;
#Nullable List<M> getItems() {
if (mModel != null) {
return mModel.getModelList();
}
return null;
}
}
And the BaseModel is
public abstract class BaseModel<M> {
private List<M> modelList;
public List<M> getModelList() {
return modelList;
}
public void setModelList(List<M> modelList) {
this.modelList = modelList;
}
}
Sub model
public class LoginModel extends BaseModel<LoginModel> {
#Override
public List<LoginModel> getModelList() {
return super.getModelList();
}
#Override
public void setModelList(List<LoginModel> modelList) {
super.setModelList(modelList);
}
}
And finally presenter is like this
public class LoginPresenter extends BasePresenter<LoginModel> {
//do your code
}
Hope it helps you.
Maybe this can help you:
List getItems(){
if(mModel instanceof TheSuperClassOrInterface){
return ((TheSuperClassOrInterface)mModel).getAll();
}else{
return null;
}
}
I have a small problem which I can't figure out to save my life.
Basically I need to register classes anytime dynamically using guice and then loop through them all.
Lets say this is my class to register Strategies but these strategies can be added anytime through the application running.
// Strategy registration may happen anytime, this is just an example
strategyManager.register(ExampleStrategy1.class);
strategyManager.register(ExampleStrategy2.class);
StrategyImpl class
public class StrategyImpl implements Strategy {
#Override
public void register(Class<? extends StrategyDispatcher> strat) {
//Add this class into provider or create an instance for it and add it into guice but how?
}
#Override
public void dispatchStrategy() {
//Find all strategies and execute them
}
}
I've tried using a Provider but have no idea how i'd add the registered class into the provider and retrieve them all?
#Override
protected void configure() {
bind(Strategy.class).toProvider(StrategyProvider.class);
}
My provider class always gets the same instance
public class StrategyProvider implements Provider<StrategyDispatcher> {
public LogManager get() {
return new StrategyDispatcherImpl();
}
}
The strategies that I add extend the StrategyDispatcherImpl class so i could cast them?
I need to add multiple binds to a same instance but it needs to be done dynamically and not using the bind method in configure but another way then be able to find all these strategies and execute them.
If you truly need it to happen at "any time" during the application life cycle then Guice then I think you will need some sort of Guice-aware Factory. I.e.
public class TestStuff {
#Test
public void testDynamicCreation() {
Injector injector = Guice.createInjector();
StrategyManager manager = injector.getInstance(StrategyManager.class);
Hello hello = injector.getInstance(Hello.class);
manager.doStuff();
assertThat(hello.helloCalled, is(false));
manager.register(Hello.class); // DYNAMIC!!
manager.doStuff();
assertThat(hello.helloCalled, is(true));
}
}
interface Strategy {
void doStuff();
}
#Singleton
class Hello implements Strategy {
boolean helloCalled = false;
public void doStuff() {
helloCalled = true;
}
}
class StrategyManager {
private final Collection<Strategy> strategies = new ArrayList<>();
private final StrategyFactory factory;
#Inject
StrategyManager(StrategyFactory factory) {
this.factory = factory;
}
public void register(Class<? extends Strategy> strat) {
strategies.add(factory.create(strat));
}
public void doStuff() {
for (Strategy s : strategies) {
s.doStuff();
}
}
}
class StrategyFactory {
private final Injector injector;
#Inject
StrategyFactory(Injector injector) {
this.injector = injector;
}
public Strategy create(Class<? extends Strategy> clazz) {
return injector.getInstance(clazz);
}
}
If it is not "dynamic" after the initialization phase then you are after the "multibinder" I think.
Could you guys please help me find where I made a mistake ?
I switched from SimpleBeanEditorDriver to RequestFactoryEditorDriver and my code no longer saves full graph even though with() method is called. But it correctly loads full graph in the constructor.
Could it be caused by circular reference between OrganizationProxy and PersonProxy ? I don't know what else to think :( It worked with SimpleBeanEditorDriver though.
Below is my client code. Let me know if you want me to add sources of proxies to this question (or you can see them here).
public class NewOrderView extends Composite
{
interface Binder extends UiBinder<Widget, NewOrderView> {}
private static Binder uiBinder = GWT.create(Binder.class);
interface Driver extends RequestFactoryEditorDriver<OrganizationProxy, OrganizationEditor> {}
Driver driver = GWT.create(Driver.class);
#UiField
Button save;
#UiField
OrganizationEditor orgEditor;
AdminRequestFactory requestFactory;
AdminRequestFactory.OrderRequestContext requestContext;
OrganizationProxy organization;
public NewOrderView()
{
initWidget(uiBinder.createAndBindUi(this));
requestFactory = createFactory();
requestContext = requestFactory.contextOrder();
driver.initialize(requestFactory, orgEditor);
String[] paths = driver.getPaths();
createFactory().contextOrder().findOrganizationById(1).with(paths).fire(new Receiver<OrganizationProxy>()
{
#Override
public void onSuccess(OrganizationProxy response)
{
if (response == null)
{
organization = requestContext.create(OrganizationProxy.class);
organization.setContactPerson(requestContext.create(PersonProxy.class));
} else
organization = requestContext.edit(response);
driver.edit(organization, requestContext);
}
#Override
public void onFailure(ServerFailure error)
{
createConfirmationDialogBox(error.getMessage()).center();
}
});
}
private static AdminRequestFactory createFactory()
{
AdminRequestFactory factory = GWT.create(AdminRequestFactory.class);
factory.initialize(new SimpleEventBus());
return factory;
}
#UiHandler("save")
void buttonClick(ClickEvent e)
{
e.stopPropagation();
save.setEnabled(false);
try
{
AdminRequestFactory.OrderRequestContext ctx = (AdminRequestFactory.OrderRequestContext) driver.flush();
if (!driver.hasErrors())
{
// Link to each other
PersonProxy contactPerson = organization.getContactPerson();
contactPerson.setOrganization(organization);
String[] paths = driver.getPaths();
ctx.saveOrganization(organization).with(paths).fire(new Receiver<Void>()
{
#Override
public void onSuccess(Void arg0)
{
createConfirmationDialogBox("Saved!").center();
}
#Override
public void onFailure(ServerFailure error)
{
createConfirmationDialogBox(error.getMessage()).center();
}
});
}
} finally
{
save.setEnabled(true);
}
}
}
with() is only used for retrieval of information, so your with() use with a void return type is useless (but harmless).
Whether a full graph is persisted is entirely up to your server-side code, which is intimately bound to your persistence API (JPA, JDO, etc.)
First, check that the Organization object you receive in your save() method on the server-side is correctly populated. If it's not the case, check your Locators (and/or static findXxx methods) ; otherwise, check your save() method's code.
Judging from the code above, I can't see a reason why it wouldn't work.
It took me some time to realize that the problem was the composite id of Person entity.
Below is the code snippet of PojoLocator that is used by my proxy entities.
public class PojoLocator extends Locator<DatastoreObject, Long>
{
#Override
public DatastoreObject find(Class<? extends DatastoreObject> clazz, Long id)
{
}
#Override
public Long getId(DatastoreObject domainObject)
{
}
}
In order to fetch child entity from DataStore you need to have id of a parent class. In order to achieve that I switched "ID class" for Locator<> to String which represents textual form of Objectify's Key<> class.
Here is how to looks now:
public class PojoLocator extends Locator<DatastoreObject, String>
{
#Override
public DatastoreObject find(Class<? extends DatastoreObject> clazz, String id)
{
Key<DatastoreObject> key = Key.create(id);
return ofy.load(key);
}
#Override
public String getId(DatastoreObject domainObject)
{
if (domainObject.getId() != null)
{
Key<DatastoreObject> key = ofy.fact().getKey(domainObject);
return key.getString();
} else
return null;
}
}
Please note that your implementation may slightly differ because I'm using Objectify4.