How to save state when using strategy pattern - java

I'm am trying to implement a feed using the strategy pattern.
I have a few different types of ways in which feeds item are retrieved, e.g. all, suggested, by a search.
public interface IGetFeedItemsStrategy{
FeedItems getFeedItems(int start, int amount);
}
The implementations looks like this:
public Class GetSuggestedFeedItemsStrategy implements IGetFeedItemsStrategy{
private FeedDao feedDao;
public GetSearchedFeedItemsStrategy(FeedDao feedDao
this.feedDao = feedDao;
}
FeedItems getFeedItems(int start, int amount){
return feedDao.getSuggestedItems(start, amount);
}
}
public Class GetSearchedFeedItemsStrategy implements IGetFeedItemsStrategy{
private FeedModel feedModel;
private FeedDao feedDao;
public GetSearchedFeedItemsStrategy(FeedDao feedDao, FeedModel feedModel){
this.feedDao = feedDao;
this.feedModel = feedModel;
}
FeedItems getFeedItems(int start, int amount){
return feedDao.getSearchedItems(start, amount, feedModel.getSearchPhrase());
}
}
When a user clicks a button to change what type of results they want the controller calls setGetFeedItemsStategy(new GetSuggestedFeedItemsStrategy) or whatever. Now whenever the controller has to refresh the feed or paginate through result it uses whatever strategy has been set.
My question is whether it is okay to save references to other 'entity' and 'service' objects in strategy class implementations? Here the feedDao was injected into the controller and the feedModel was created by feedModel = new FeedModel() in the constructor. I'm confused because I've read that entities and services should be kept seperate. e.g. (http://thinkbeforecoding.com/post/2009/03/04/How-not-to-inject-services-in-entities). I'm wondering whether a strategy object is either?

Related

Axon: Create and Save another Aggregate in Saga after creation of an Aggregate

Update: The issue seems to be the id that I'm using twice, or in other words, the id from the product entity that I want to use for the productinventory entity. As soon as I generate a new id for the productinventory entity, it seems to work fine. But I want to have the same id for both, since they're the same product.
I have 2 Services:
ProductManagementService (saves a Product entity with product details)
1.) For saving the Product Entity, I implemented an EventHandler that listens to ProductCreatedEvent and saves the product to a mysql database.
ProductInventoryService (saves a ProductInventory entity with stock quantities of product to a certain productId defined in ProductManagementService )
2.) For saving the ProductInventory Entity, I also implemented an EventHandler that listens to ProductInventoryCreatedEvent and saves the product to a mysql database.
What I want to do:
When a new Product is created in ProductManagementService, I want to create a ProductInventory entity in ProductInventoryService directly afterwards and save it to my msql table. The new ProductInventory entity shall have the same id as the Product entity.
For that to accomplish, I created a Saga, which listes to a ProductCreatedEvent and sends a new CreateProductInventoryCommand. As soon as the CreateProductInventoryCommand triggers a ProductInventoryCreatedEvent, the EventHandler as described in 2.) should catch it. Except it doesn't.
The only thing thta gets saved is the Product Entity, so in summary:
1.) works, 2.) doesn't. A ProductInventory Aggregate does get created, but it doesn't get saved since the saving process that is connected to an EventHandler isn't triggered.
I also get an Exception, the application doesn't crash though: Command 'com.myApplication.apicore.command.CreateProductInventoryCommand' resulted in org.axonframework.commandhandling.CommandExecutionException(OUT_OF_RANGE: [AXONIQ-2000] Invalid sequence number 0 for aggregate 3cd71e21-3720-403b-9182-130d61760117, expected 1)
My Saga:
#Saga
#ProcessingGroup("ProductCreationSaga")
public class ProductCreationSaga {
#Autowired
private transient CommandGateway commandGateway;
#StartSaga
#SagaEventHandler(associationProperty = "productId")
public void handle(ProductCreatedEvent event) {
System.out.println("ProductCreationSaga, SagaEventHandler, ProductCreatedEvent");
String productInventoryId = event.productId;
SagaLifecycle.associateWith("productInventoryId", productInventoryId);
//takes ID from product entity and sets all 3 stock attributes to zero
commandGateway.send(new CreateProductInventoryCommand(productInventoryId, 0, 0, 0));
}
#SagaEventHandler(associationProperty = "productInventoryId")
public void handle(ProductInventoryCreatedEvent event) {
System.out.println("ProductCreationSaga, SagaEventHandler, ProductInventoryCreatedEvent");
SagaLifecycle.end();
}
}
The EventHandler that works as intended and saves a Product Entity:
#Component
public class ProductPersistenceService {
#Autowired
private ProductEntityRepository productRepository;
//works as intended
#EventHandler
void on(ProductCreatedEvent event) {
System.out.println("ProductPersistenceService, EventHandler, ProductCreatedEvent");
ProductEntity entity = new ProductEntity(event.productId, event.productName, event.productDescription, event.productPrice);
productRepository.save(entity);
}
#EventHandler
void on(ProductNameChangedEvent event) {
System.out.println("ProductPersistenceService, EventHandler, ProductNameChangedEvent");
ProductEntity existingEntity = productRepository.findById(event.productId).get();
ProductEntity entity = new ProductEntity(event.productId, event.productName, existingEntity.getProductDescription(), existingEntity.getProductPrice());
productRepository.save(entity);
}
}
The EventHandler that should save a ProductInventory Entity, but doesn't:
#Component
public class ProductInventoryPersistenceService {
#Autowired
private ProductInventoryEntityRepository productInventoryRepository;
//doesn't work
#EventHandler
void on(ProductInventoryCreatedEvent event) {
System.out.println("ProductInventoryPersistenceService, EventHandler, ProductInventoryCreatedEvent");
ProductInventoryEntity entity = new ProductInventoryEntity(event.productInventoryId, event.physicalStock, event.reservedStock, event.availableStock);
System.out.println(entity.toString());
productInventoryRepository.save(entity);
}
}
Product-Aggregate:
#Aggregate
public class Product {
#AggregateIdentifier
private String productId;
private String productName;
private String productDescription;
private double productPrice;
public Product() {
}
#CommandHandler
public Product(CreateProductCommand command) {
System.out.println("Product, CommandHandler, CreateProductCommand");
AggregateLifecycle.apply(new ProductCreatedEvent(command.productId, command.productName, command.productDescription, command.productPrice));
}
#EventSourcingHandler
protected void on(ProductCreatedEvent event) {
System.out.println("Product, EventSourcingHandler, ProductCreatedEvent");
this.productId = event.productId;
this.productName = event.productName;
this.productDescription = event.productDescription;
this.productPrice = event.productPrice;
}
}
ProductInventory-Aggregate:
#Aggregate
public class ProductInventory {
#AggregateIdentifier
private String productInventoryId;
private int physicalStock;
private int reservedStock;
private int availableStock;
public ProductInventory() {
}
#CommandHandler
public ProductInventory(CreateProductInventoryCommand command) {
System.out.println("ProductInventory, CommandHandler, CreateProductInventoryCommand");
AggregateLifecycle.apply(new ProductInventoryCreatedEvent(command.productInventoryId, command.physicalStock, command.reservedStock, command.availableStock));
}
#EventSourcingHandler
protected void on(ProductInventoryCreatedEvent event) {
System.out.println("ProductInventory, EventSourcingHandler, ProductInventoryCreatedEvent");
this.productInventoryId = event.productInventoryId;
this.physicalStock = event.physicalStock;
this.reservedStock = event.reservedStock;
this.availableStock = event.availableStock;
}
}
What you are noticing right now is the uniqueness requirement of the [aggregate identifier, sequence number] pair within a given Event Store. This requirement is in place to safe guard you from potential concurrent access on the same aggregate instance, as several events for the same aggregate all need to have a unique overall sequence number. This number is furthermore use to identify the order in which events need to be handled to guarantee the Aggregate is recreated in the same order consistently.
So, you might think this would opt for a "sorry there is no solution in place", but that is luckily not the case. There are roughly three things you can do in this set up:
Life with the fact both aggregates will have unique identifiers.
Use distinct bounded contexts between both applications.
Change the way aggregate identifiers are written.
Option 1 is arguably the most pragmatic and used by the majority. You have however noted the reuse of the identifier is necessary, so I am assuming you have already disregarded this as an option entirely. Regardless, I would try to revisit this approach as using UUIDs per default for each new entity you create can safe you from trouble in the future.
Option 2 would reflect itself with the Bounded Context notion pulled in by DDD. Letting the Product aggregate and ProductInventory aggregate reside in distinct contexts will mean you will have distinct event stores for both. Thus, the uniqueness constraint would be kept, as no single store is containing both aggregate event streams. Whether this approach is feasible however depends on whether both aggregates actually belong to the same context yes/no. If this is the case, you could for example use Axon Server's multi-context support to create two distinct applications.
Option 3 requires a little bit of insight in what Axon does. When it stores an event, it will invoke the toString() method on the #AggregateIdentifier annotated field within the Aggregate. As your #AggregateIdentifier annotated field is a String, you are given the identifier as is. What you could do is have typed identifiers, for which the toString() method doesn't return only the identifier, but it appends the aggregate type to it. Doing so will make the stored aggregateIdentifier unique, whereas from the usage perspective it still seems like you are reusing the identifier.
Which of the three options suits your solution better is hard to deduce from my perspective. What I did do, is order them in most reasonable from my perspective.
Hoping this will help your further #Jan!

How to structure email request class for different types of emails requiring different rendering params?

Currently, my notification request is like this:
public class EmailRequest{
public enum EmailType{
TYPE_1,
TYPE_2,
...
}
EmailType emailType;
String toAddress;
EmailRenderer renderer;
}
where EmailRenderer is an interface
public interface EmailRenderer{
EmailMessage render()
}
Now, each type of email has a separate implementation of the renderer interface and each implementation contains some rendering data that has to be provided by the client. This data can be different for each implementation.
Example:
public class Type1EmailRenderer implements EmailRenderer{
String param1;
String param2;
#Override
EmailMessage render(){
//rendering logic using the params
}
}
But, it seems redundant to me for the user to set the email type and renderer as well. Choosing the renderer should automatically get me the emailType. How should I restructure the request to be free of this redundancy? Also, can I use any design pattern for providing the renderers to my users?
I'll base my answer on a claim that,
putting aside programming-related questions, at the level of human logic, it looks to me strange that if I want to send an email I should know about renderers at all.
In my understanding If I have emails of different types (you've called them TYPE_1 and TYPE_2, let's give more "business" names for better clarity, like "dailyReport" or "advertisement", you'll see later why) I should just prepare a request with my data (param1, param2) and send it. I shouldn't care about renderers at all as long as the same email type assumes that the same type of renderer will be used.
So, lets say, type "advertisement" has a mandatory parameter String topic and optional parameter String targetAudience and type "dailyReport" has Integer totalUsersCount and optional String mostActiveUserName.
In this case, I propose the somewhat hybrid approach mainly based on Builder creation pattern:
public class EmailRequestBuilder {
private String toAddress;
private EmailRequestBuilder(String to) {
this.toAddress = to;
}
public static EmailRequestBuilder newEmailRequest(String to) {
return new EmailRequestBuilder(to);
}
public AdvertisementBuilder ofAdvertisementType(String topic) {
return new AdvertisementBuilder(topic, this);
}
public DailyReportBuilder ofDailyReportType(Integer totalUsersCount) {
return new DailyReportBuilder(totalUsersCount, this);
}
// all builders in the same package, hence package private build method,
// concrete email type builders will call this method, I'll show at the end
EmailRequest build(EmailType type, EmailRenderer emailRenderer) {
return new EmailRequest (to, type, emailRenderer);
}
}
public class AdvertisementBuilder {
private String topic;
private EmailRequestBuilder emailRequestBuilder;
// package private, so that only EmailRequestBuilder will be able to create it
AdvertisementBuilder(String topic, EmailRequestBuilder emailRequestBuilder) // mandatory parameters in constructor + reference to already gathered data {
this.topic = topic;
this.emailRequestBuilder = emailRequestBuilder;
}
// for optional parameters provide an explicit method that can be called
// but its not a mandatory call
public AdvertisementBuilder withTargetAudience(String audience) {
this.audience = audience;
return this;
}
public EmailRequest buildRequest() {
EmailRenderer renderer = new AdvertisementRenderer(topic, audience);
return emailRequestBuilder.build(EmailType.ADVERTISEMENT, renderer);
}
}
// A similar builder for DailyReport (I'll omit it but assume that there is a class
class DailyReportBuilder {}
Now the good part about it that now you can't go wrong as a user. A typical interaction with such a construction will be:
EmailRequest request = EmailRequestBuilder.newEmailRequest("john.smith#gmail.com")
.ofAdvertisementType("sample topic") // its a mandatory param, you have to supply, can't go wrong
.withTargetAudience("target audience") // non-mandatory call
.buildRequest();
Couple of notes:
Once you pick a type by calling ofDailyReportType/ ofAdvertisementType the user can't really supply parameters of different email type, because it gets "routed" to the builder that doesn't have methods for wrong parameters. An immediate implication of this is that an autocomplete will work in your IDE and people who will use this method will thank you about it ;)
It's easy to add new email types this way, no existing code will change.
Maybe with this approach, an enum EmailType will be redundant. I've preserved it in my solution but probably you'll drop it if it's not required.
Since I sometimes restrict the visibility (package private build methods, constructors, and so forth) - it will be __the_only__way to create the request which means that no-one will create "internal" objects only because it's possible to do so. At least a malicious programmer will think twice before breaking encapsulation :)
For example you can use "factory method".
EmailRenderer createRenderer(EmailType type) {
switch (type) {
case: TYPE_1:
return new RendererType1();
case: TYPE_2:
return new RendererType2();
...
}
}
Also, you probably can introduce cashing of this objects in order not to create them every time. Maybe some lazy initialization (you create appropriate Renderer first time when you needed and after that always return that same instance).

how to make ArrayList accessible by all JFrames and how to update it?

So I'm making a mock Starbucks app and I want that everytime a customer clicks the "Order" button, the product is added to an ArrayList and for this ArrayList to be accessed by all. I'm kind of confused where to insert the global ArrayList code...
This is code for my btnOrder:
private void btnOrderActionPerformed(java.awt.event.ActionEvent evt) {
String name = lblName.getText();
String size = cmbSize.getSelectedItem().toString();
int quantity = (int) spnrQuantity.getValue();
int price=0;
if (size.equals("Tall 12oz")) {
price = 170;
} else if (size.equals("Grande 16oz")) {
price = 180;
} else if (size.equals("Venti 20oz")) {
price = 190;
}
Global.list.add(new Object());
new Receipt(name, size, quantity, price).setVisible(true);
}
This is code for my Receipt frame which contains the JTable so I can display orders:
public class Receipt extends javax.swing.JFrame {
/**
* Creates new form Receipt
*/
public Receipt() {
initComponents();
}
String size, name;
int quantity, price;
public Receipt(String name, String size, int quantity, int price) {
initComponents();
this.name = name;
this.size = size;
this.quantity = quantity;
this.price = price;
addToTable();
}
void addToTable() {
DefaultTableModel table = (DefaultTableModel) tblCart.getModel();
Vector v = new Vector();
v.add(name);
v.add(size);
v.add(price);
v.add(quantity);
table.addRow(v);
}
And this is the code for the accessible ArrayList:
public class Global {
public static ArrayList<Object> list = new ArrayList<>();
private Global(){
}
}
Managing global state can be a nightmare, while you can use a singleton to solve the issue, it violates the Single responsibility principle. It also removes access control, allowing anyone to modify the list in whatever way they see fit without control.
Another solution is to use some kind of model, which can passed between the various components, if you make clever use of interfaces, you can control who can do what and when.
This is a core concept of Model-View-Controller and program to interface not implementation principle.
The basic idea is you would create a "model" which maintains the data you want to share, in this, primarily the items in the customer's order (and maybe the customer's name)
You would create an appropriate order and pass a reference of it to the "order" view, where it would be able to add/remove/update items to the model. When complete, the "controller" would then pass the same instance of the model to the "check-out" view, which would use this information to generate a bill (and possibly a payment information) and finally store the transaction
You would then be able to take the information from the model at the end and tell what has happened.
Because there are complex states you might need to control, you might need more than one model, for example, you could pass the "order" model to the "check-out" view, but it could create a "transaction" model, which wraps the "order" model
You can take use Singleton design pattern here. With Singletons, you can take advantage of Polymorphism which won't be possible with static objects.
enum Global {
INSTANCE;
private ArrayList<Object> list = new ArrayList<>();
public void add(Object obj) {
//custom validations (if any)
list.add(obj);
}
public Object get(int index) {
//check here for permissions, validations etc...
return list.get(index);
}
//other methods to access your shared objects
...
}
In this example, singleton pattern is implemented using ENUMs which ensures thread safety. You can also implement singleton using The ‘Inner Class’ Approach which is also thread safe.
Usage
private void btnOrderActionPerformed(java.awt.event.ActionEvent evt) {
...
Global.INSTANCE.add(new Object());
new Receipt(name, size, quantity, price).setVisible(true);
}
Difference between static class and singleton pattern?

Coding style and organization

So I am currently making a airplane reservation system for a summer project to keep fresh with Java. With any reservation system its requiring a lot of classes and methods. Currently I'm working on importing the fleet.
My main method is acting like the chronological guide to my program.
public static void main(String[] args){
//start here
//accept passenger credentials
//place passenger in seat on plane
}
My question is a formatting problem. When I'm looking to start "making" my aircraft for my fleet. It goes a little like this.
//...
Airplane Boeing737 = new Airplane(seats[], nameOfAircraft);
This will put all values that i need to construct my airplane, obviously there are more variables for the airplane constructor.
My thought is to make a method in the Airplane class that will do this for me. but in order to do this i need to call a blank constructor for the other class (the one with my main method) to see it. I feel like this is horrible form for some reason. Is there a better way to do this?
Another thought as I'm posting is to modify the constructor to not accept any arguments and have that do everything in there. I feel like that's what I should be doing but I'm not 100% sure that would be the correct choice. I guess my overall question would be what are best practices in situations like this.
Use builder pattern, this will allow you:
dynamic way of building events
maintainable code (you can add more params when you want)
preserve integrity of the objects when created
Joshua Bloch's in Effective Java Chapter 1 Item 2 states:
Luckily, there is a third alternative that combines the safety of the telescoping
constructor pattern with the readability of the JavaBeans pattern. It is a form of the
Builder pattern. Instead of making the desired object directly,
the client calls a constructor (or static factory) with all of the required parameters and gets a builder object.
Modifying his example:
//Builder Pattern
public class Airplane {
private final int[] seats;
private final String name;
private final int maxSpeed;
private final int maxPassengers;
public static class Builder {
// Required parameters
private final int[] seats;
private final String name;
// Optional parameters - initialized to default values
private int maxSpeed = 1000;
private int maxPassengers = 150;
public Builder(int[] seats, String name) {
this.seats = seats;
this.name = name;
}
public Builder maxSpeed(int val) {
maxSpeed = val;
return this;
}
public Builder maxPassengers(int val) {
maxPassengers = val;
return this;
}
public Airplane build() {
return new Airplane(this);
}
}
private Airplane(Builder builder) {
seats = builder.seats;
name = builder.name;
maxSpeed = builder.maxSpeed;
maxPassengers = builder.maxPassengers;
}
}
Then you can create several different airplanes
public static void main(String[] args) {
// only mandatory params
Airplane boeing747 = new Airplane.Builder(new int[] {1,0,1}, "boeing747").build();
// just one param
Airplane boeing646 = new Airplane.Builder(new int[] {1,1,1}, "boeing646").maxPassengers(250).build();
// all params
Airplane fighter = new Airplane.Builder(new int[] {1,0,0}, "fighter_1").maxPassengers(3).maxSpeed(1600).build();
}
Forget the main method for now, you don't know if it will be a command line program, desktop app with a UI, web service or what. You don't know if it will be standalone or hosted in some framework or application server.
I would suggest starting with unit tests and drive the design of your domain model / business logic with TDD.
You don't want to see anything like Boeing737 hard coded like that. It will get its input from some other source, e.g. typed in, xml file, existing database, some other system.
You will then create instances of Airplane dynamically. You will pass something like a DTO from the UI or DB or XML parser to the constructor. There are other ways, look up Factory Pattern for example, but they tend to get overused IMHO.
You seem to be starting off in a way that doesn't match anything anyone does in the real world. Its hard to give any better advice.

Pattern for persisting data in Realm?

My issue is how to organize the code. Let say I have a User class
public class User extends RealmObject {
#PrimaryKey
private String id;
#Required
private String name;
public User() { // per requirement of no args constructor
id = UUID.randomUUID().toString();
}
// Assume getter & setter below...
}
and a Util class is needed to handles the save in an asynchronous manner since RealmObjects cannot have methods other than getter/setter.
public class Util {
public static void save(User user, Realm realm) {
RealmAsyncTask transaction = realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.copyToRealm(user); // <====== Argument needs to be declared final in parent method's argument!
}
}, null);
}
}
The intention is to put save() in a Util class to prevent spreading similar save code all over the code-base so that every time I wanted to save I would just call it as such:
User u = new User();
u.setName("Uncle Sam");
Util.save(u, Realm.getDefaultInstance());
Not sure if this affects performance at all, but I was just going to save all fields overwriting what was there except for the unique id field every single time.
The problem is that I now need to set the "user" argument as final in the Util.save() method, which means I cannot pass in the object I need to save other than once.
Is there a different way of handling this? Maybe a different pattern? Or am I looking at this all wrong and should go back to SQLite?
Why is it a problem to set public static void save(final User user, Realm realm) ? It just means you cannot reassign the user variable to something else.
That said, the existence of a save() method can be a potential code smell as you then spread the update behaviour across the code base. I would suggest looking into something like the Repository pattern (http://martinfowler.com/eaaCatalog/repository.html) instead.
Realm is actually working on an example showing how you can combine the Model-View-Presenter architecture with a Repository to encapsulate updates which is a good pattern for what you are trying to do here. You can see the code for it here: https://github.com/realm/realm-java/pull/1960

Categories