I'm working with a Spring web project but I'm facing a problem with an instance variable, I use a List to store a report data, when a user request this report I store this List in order to use it later for an Excel generation, but when another user requests the same report the List is re-write with the new data requested and when the first user download the report, it comes with the data that was requested form the second user.
My class:
public class foo{
List<Service> services;
GetMapping({"/Report/Detail"})
String getReport(Parameters params, ModelMap model){
services = new ArrayList<>();
//A lot of stuff
services = serviceRepository(params);
//A lot of stuff
model.addAttribute("services",services)
return "ReportDetail";
}
GetMapping({"/Report/Detail/Excel"})
byte[] getExcelReport(){
//Using the List<services> here to download the report
//this List is getting modified by the second user
byte[] excelReport = excelService(services);
return excelReport;
}
}
I don't want to do major changes because the class is too large, it works perfect but I have this problem and I'm looking for a workaround.
Any advice will apreciate.
Best!
Every time a user sends a request to /Report/Detail you overwrite the services list. If you want each user to have their own list then you have to use a different approach. For example you could use a Map that stores users (key should uniquely identify the user) and their respective lists.
Map<UserKey, List<Service>> services;
And later in the method get the correct list by
List<Service> userServices = services.get(userKey);
In case of distributed application, you would of course have to use a distributed map (possibilities include for example Hazelcast or Ehcache)
Related
This question already has an answer here:
DDD - how to rehydrate
(1 answer)
Closed 4 years ago.
After starting using ddd in a project i have the following architecture :
domain model which contains my aggregate root (AR), my entities and my value objects
repository interface (implemented in the infrastructure part)
application services to create, delete and update the AR. The application services used to update the AR work this way : find the AR from an ID in the database, call some methods, then save it in the database
Nb: i have only one AR because it is supposed to be a microservice and i only talk about the "command" side here.
I need 2 ways to instantiate the AR :
one when calling the application service to create the AR from inputs
one when retrieving the existing AR from the database, i don't really want to do all the checks
In the first case i need to create an id, do some check, etc.
In the second case I just want to recreate the AR from the data contained in the database.
How/where am i supposed to do that?
For the creation from input, i can do it in the application service like that (it is a simple example) :
public class CreateUser {
private final UserRepository userRepository;
public User execute(String name) {
User user = new User(UUID.randomUUID(), name);
return userRepository.create(user);
}
}
For loading the AR from the database, i can either :
user the same constructor doing some validation
create a new one without validation (i don't really like the idea of having a constructor in the AR bypassing all the validation)
Any ideas on how to do this elegantly?
You are wrong in the concept of creating a new instance of the aggregate using a constructor when you load it from the database. You don't have to call any constructor nor factory nor validate any fields. Just get it from the repository with a getAggregateOfId method which returns the aggregate already constructed with the state stored in the database.
I need some of your inputs in deciding a right approach in following case.
I am currently working on a ecommerce application (An online shopping website). Here, on homepage of application, I have to display a list of products available in shop. The end user has a facility of applying filters (include/exclude) to products list so that only the products satisfying the applied filter will be displayed.
So, my question is regarding the correct design for applying these filter on products in Java layer. Please note I keep all the data in-memory (hashmap) at Java layer. I just want to apply filters that are passed as an input from UI on this in-memory data store and return back the filtered results.
Backend: Java application hosted on Tomcat. This application has a periodic thread running that reads/refreshes product data from file system every 30 seconds and keeps it in-memory of java process.
Frontend: React application hosted on Nginx. Makes rest calls to backend server to fetch the data.
Approaches I considered:
Create a class called "FilteredProducts" that has attribute (say filtering criteria). Have different implementations for each possible filtering criteria using strategy pattern and apply the filtering criteria on products based on filtering criteria that is passed as an input.
Can anyone please guide me, if there is any recommended way to handle this requirement? Any input is highly appreciated. Please let me know if more information is required in this context.
You could create an interface or abstract class filter and for each filter element you could create a specific class that implements or extends the interdace/superclass.
Then you could implement a matches method and check, which articles meet the criterias (e.g.:)
public interface FilterCriteria() {
public List<ShopElement> getMatchedProducts(int minPrice, int maxPrice);
}
public class PriceFilterCriteria implements FilterCriteria() {
#Override
public List<ShopElement> getMatchedProducts(int minPrice, int maxPrice) {
List<ShopElement> matchedProducts = new ArrayList<>();
foreach(ShopElement se : YourDataSource.getAllElements() ) {
if(se.getPrice() > minPrice && se.getPrice() < maxPrice) {
matchedProducts.add(se);
}
}
}
}
This pattern is really called filter pattern.
Your strategy pattern approach may work, but i think it is some kind of 'wrong-placed' in this context, because i think strategie pattern is mostly for changing concrete implementations within a client and not for combining various, cross-cutting filters.
I currently have the following issue:
I am looking for a proper way to store a large java object on some kind of server, which could be a MySQL database or Google App Engine. I have found a lot of ways to 'store' an object, but I am looking for some advice what's best in this case:
Case
I have created some sort of shop management system for small businesses. Users of the app can generate reports about e.g. sales. I want to create the functionality to save these reports, such that they can be generated later in time, without setting all the options for it again.
Class
The layout of the Report class can be found below (I have excluded the getters, setters and list operators):
public class Report {
/* ATTRIBUTES */
public IntegerProperty ID = new SimpleIntegerProperty();
public StringProperty name = new SimpleStringProperty();
public Employee employee = null;
public BooleanProperty timeFilterPresent = new SimpleBooleanProperty();
public StringProperty optionalBasicFilterStatement = new SimpleStringProperty();
/* Categories */
public ReportCategory category;
public ReportSubcategory subCategory;
/* Filters */
public List<Filter> filters = new ArrayList<>();
/* Views */
public List<ReportView> views = new ArrayList<>();
public List<VBox> generatedViews = new ArrayList<>();
/* Queries */
public List<Query> queries = new ArrayList<>();
/* Time intervals */
public List<TimeInterval> timeIntervals = new ArrayList<>();
As you can see, this is a pretty large class. All of the other classes that are mentioned in the Report class, are also custom made (such as Filter, Employee, ReportCategory etc).
Options to store the object
I have found the following options for saving this object:
Make the class Serializable, convert the object to a byte array and store it in a MySQL database
I have tried this, but it would be a lot of work to make all the sub-classes Serializable as well, and I am not even sure if this would work properly in this case.
Use Gson to convert the object to JSON, and store this in a MySQL database as plain text
When I just try this without any tweaking, I get a StackOverflow error. I could create a custom Json-Converter for this class, but then I would need to do this for every subclass too. Also, I would have to make a converter from JSON to an object.
Store object on Google App Engine, by also defining the necessary classes there
I would have to duplicate all the classes on the Google App Engine, which is not practical when I change in the class or some of the subclasses is made. I could serve the object as a Blob to my application.
Create MySQL tables for these classes
I could create separate tables for these classes, but then I need to create a lot of tables for only one single usage.
All of these options have their (dis-)advantages, and because I do not have any experience with storing java objects, I would like to know if I am missing any options and which of the options you prefer. All of these options take some time to implement, so I want to be sure to choose the correct one.
Any help is greatly appreciated!
I'm creating tasks with various properties and I'm passing the JSON data from Angular frontend to Java based backend. Assignee is a property of the Task class at the moment.
A new request came in to change the behavior: The user should be able to select multiple assignees upon creating a new task.
The way I want to handle this is that I want to create the same amount of tasks as the number of assignees passed. So if n users are passed with the various task data, n tasks would be created in the DB for each user as an assignee.
Previously I could only pass one assignee and the code for returning the POST request's response was the following:
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response save(TaskInDto taskInDto) {
// saving to DB, etc...
String taskId = createdTask.getId().toString();
URI taskUri = uriInfo.getAbsolutePathBuilder().path(taskId).build();
return Response.created(taskUri).build();
}
My question is regarding REST design: What should I return as a Result object to the user if multiple objects were created?
If a POST request is creating multiple objects, clients will expect back a response entity containing links to each created resource.
The first thing my GWT app does when it loads is request the current logged in user from the server via RequestFactory. This blocks because I need properties of the User to know how to proceed. This only takes < 500ms, but it really annoys me that the app is blocked during this time. I already have the User on the server when the jsp is generated, so why not just add the serialized User to the jsp and eliminate this request altogether?
I have two problems keeping me from doing this:
I need to transform User to UserProxy
I need to serialize UserProxy in a way that is easy for GWT to deserialize.
I have not figured out a good way to do #1. This logic appears to be buried in ServiceLayerDecorator without an easy way to isolate? I may be wrong here.
The second one seems easier via ProxySerializer But how do I get my hands on the requestfactory when I am on the server? You cannot call GWT.create on the server.
I have been looking into AutoBeans but this does not handle #1 above. My UserProxy has references to collections of other EntityProxy's that I would like to maintain.
It is possible using AutoBeans if you create an AutoBeanFactory for your proxies:
To transform User to UserProxy:
Create a server side RequestFactory and invoke the same normal request. Response will contain UserProxy (but on the server).
To serialize UserProxy:
AutoBean<UserProxy> bean = AutoBeanUtils.getAutoBean(receivedUserProxy);
String json = AutoBeanCodex.encode(bean).getPayload();
To deserialize UserProxy on client:
AutoBean<UserProxy> bean = AutoBeanCodex.decode(userAutoBeanFactory, UserProxy.class, json);
Creating an in-process RequestFactory on the server (tutorial):
public static <T extends RequestFactory> T create( Class<T> requestFactoryClass ) {
ServiceLayer serviceLayer = ServiceLayer.create();
SimpleRequestProcessor processor = new SimpleRequestProcessor( serviceLayer );
T factory = RequestFactorySource.create( requestFactoryClass );
factory.initialize( new SimpleEventBus(), new InProcessRequestTransport(processor) );
return factory;
}
You could use AutoBeans for this as well if you are able to make User implements UserProxy. It works since Proxies are interfaces with getters/setters:
interface UserFactory implements AutoBeanFactory
{
AutoBean<UserProxy> user(UserProxy toWrap); // wrap existing instance in an AutoBean
}
Then on server you can create the autobean and serialize to json:
UserFactory factory = AutoBeanFactorySource.create(UserFactory.class)
AutoBean<UserProxy> userProxyBean = factory.user( existingUserPojo );
// to convert AutoBean to JSON
String json = AutoBeanCodex.encode(userProxyBean).getPayload();
On the client you can just use AutoBeanCodex.decode to deserialize JSON back to a bean
You cannot call GWT.create on the server (or from any real JVM), but in many cases you can call a JVM-compatible method designed for server use instead. In this case, take a look at RequestFactorySource.create.
It can be a little messy to get the server to read from itself and print out data using RequestFactory - here is a demo example of how this can work (using gwt 2.4, the main branch has the same thing for 2.3 or so) https://github.com/niloc132/tvguide-sample-parent/blob/gwt-2.4.0/tvguide-client/src/main/java/com/acme/gwt/server/TvViewerJsonBootstrap.java - not quite the same thing that you are after, but it may be possible to use this same idea to populate a string in a proxy store that can be read in the client (seen here https://github.com/niloc132/tvguide-sample-parent/blob/gwt-2.4.0/tvguide-client/src/main/java/com/acme/gwt/client/TvGuide.java).
The basic idea is to create a request (including ids, invocations, and with() arguments so the proxy builder makes all the right pieces in a consistent way), and pass it into a SimpleRequestProcessor instance, which will then run it through the server pieces it normally would. (Any entity management system probably should still have the entities cached to avoid an additional lookup, otherwise you need to model some of the work SRP doesn internally.) The ProxySerializer, which wraps a ProxyStore, expects to have full RF messages as sent from the server, so a fair bit of message bookkeeping needs to be done correctly.
I found the answer on the GWT Google Group. All credits go to Nisha Sowdri NM.
Server side encoding:
DefaultProxyStore store = new DefaultProxyStore();
ProxySerializer ser = requests.getSerializer(store);
final String key = ser.serialize(userProxy);
String message = key + ":" + store.encode();
Client side decoding:
String[] parts = message.split(":", 2);
ProxyStore store = new DefaultProxyStore(parts[1]);
ProxySerializer ser = requests.getSerializer(store);
UserProxy user = ser.deserialize(UserProxy.class, parts[0]);