Store data not in database - spring

I want to implement simple chat but store them only during server work. I don't want to store them in database, just like in List or Map. How to?

This solution works for "Simple" chat as you explained.
There isn't much information on how you had built this before so I'm just going to explain how to have an Application scoped bean that can be injected into other beans to handle storing chat.
You can configure a Service to store this information.
ChatHistoryService.java
#Service
#Scope("application")//This is the key this will keep the chatHistory alive for the length of the running application(As long as you don't have multiple instances deployed(But as you said it's simple so it shouldn't)
public class ChatHistoryService {
List<String> chatHistory = new LinkedList<>();//Use LinkedList to maintain order of input
public void storeChatMessage(String chatString) {
chatHistory.add(chatString);
}
public List<String> getChatHistory() {
//I would highly suggest creating a defensive copy of the chat here so it can't be modified.
return Collections.unmodifiableList(chatHistory);
}
}
YourChatController.java
#Controller
public class YourChatController {
#Autowired
ChatHistoryService historyService;
...I'm assuming you already have chat logic but you aren't storing the chat here is where that would go
...When chat comes in call historyService.storeChatMessage(chatMessage);
...When you want your chat call historyService.getChatHistory();
}
Once again keep in mind that this really only works for a simple application. If it's distributed there will be different chat histories per instance of the application at that point you could look into a distributed cache.
In any case don't go beyond simple with this implementation.
If you look here it will give you an idea of several caches that work with spring boot.
https://github.com/spring-projects/spring-boot/tree/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache

Related

guava eventbus post after transaction/commit

I am currently playing around with guava's eventbus in spring and while the general functionality is working fine so far i came across the following problem:
When a user want's to change data on a "Line" entity this is handled as usual in a backend service. In this service the data will be persisted via JPA first and after that I create a "NotificationEvent" with a reference to the changed entity. Via the EventBus I send the reference of the line to all subscribers.
public void notifyUI(String lineId) {
EventBus eventBus = getClientEventBus();
eventBus.post(new LineNotificationEvent(lineId));
}
the eventbus itself is created simply using new EventBus() in the background.
now in this case my subscribers are on the frontend side, outside of the #Transactional realm. so when I change my data, post the event and let the subscribers get all necessary updates from the database the actual transaction is not committed yet, which makes the subscribers fetch the old data.
the only quick fix i can think of is handling it asynchronously and wait for a second or two. But is there another way to post the events using guava AFTER the transaction has been committed?
I don't think guava is "aware" of spring at all, and in particular not with its "#Transactional" stuff.
So you need a creative solution here. One solution I can think about is to move this code to the place where you're sure that the transaction has finished.
One way to achieve that is using TransactionSyncrhonizationManager:
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization(){
void afterCommit(){
// do what you want to do after commit
// in this case call the notifyUI method
}
});
Note, that if the transaction fails (rolls back) the method won't be called, in this case you'll probably need afterCompletion method. See documentation
Another possible approach is refactoring your application to something like this:
#Service
public class NonTransactionalService {
#Autowired
private ExistingService existing;
public void entryPoint() {
String lineId = existing.invokeInTransaction(...);
// now you know for sure that the transaction has been committed
notifyUI(lineId);
}
}
#Service
public class ExistingService {
#Transactional
public String invokeInTransaction(...) {
// do your stuff that you've done before
}
}
One last thing I would like to mention here, is that Spring itself provides an events mechanism, that you might use instead of guava's one.
See this tutorial for example

Spring Boot - Camel - Tracking an exchange all the way through

We are trying to setup a very simple auditing database table for a very complex Spring Boot, Camel application with many routes (mostly internal routes using seda://)...the idea being we record in the database table each route's processing outcome. Then when issues arise we can login to the database, query the table and pinpoint exactly where the issue happened. I thought I could just use the exchange-id as the unique tracking identifier, but quickly learned that all the seda:// routes make new exchanges, or at least that's what I'm seeing (camel version 2.24.3). Frankly, I don't care what we use for the unique identifier...I can generate a UUID easily enough and the use the exchange.setProperty("id-unique", UUID).
I did manage to get something to work using the exchange.setProperty("id-exchange", exchange.getExchangeId()) and have it persist the unique identifier thru the routes...(I did read that certain pre-defined route prefixes such as jms:// will not persist exchange properties though). The thought being, the very first Processor places the exchangeId (unique-id) on the exchange properties, my tracking logic is in a processor that I can include as part of the Route's definition :
#Override
public void configure() throws Exception {
// EVENTS : Collect statistics from Camel events
this.getContext().getManagementStrategy().addEventNotifier(this.camelEventNotifier);
// INITIAL : ${body} exchange coming from a simple URL endpoint
// POST request with an XML Message...simulates an MQ
// message from Central MQ. The Web/UI service places the
// message onto the camel route using producerTemplate.
from("direct:" + Globals.ROUTEID_LBR_INTAKE_MQ)
.routeId(Globals.ROUTEID_LBR_INTAKE_MQ)
.description("Loss Backup Reports MQ XML inbound messages")
.autoStartup(false)
.process(processor)
.process(getTrackingProcessor())
.to("seda:" + Globals.ROUTEID_LBR_VALIDATION)
.end();
}
This Proof-of-Concept (POC) allowed me to at least get things tracking like we want...note multiple rows with the same unique identifier :
ID_ROW ID_EXCHANGE PROCESS_GROUP PROCESS_STEP RESULTS_STEP RESULTS_MESSAGE
1 ID-LIBP45P-322256M-1603188596161-4-6 Loss Backup Reports lbr-intake-mq add lbr-intake-mq
2 ID-LIBP45P-322256M-1603188596161-4-6 Loss Backup Reports lbr-validation add lbr-intake-mq
Thing is, this POC is proving to be rigid and difficult to record outcomes such as SUCCESS versus EXCEPTION.
My question is, has anyone done anything like this? And if so, how was it implemented? Or is there a fancy way in Camel to handle this that I just couldn't find on the web?
My other ideas were :
Set an old fashion Abstract TrackerProcessor class that all my tracked Processors extend. Then just have a handful of methods in there to create, update, etc... Each processor then just calls inherited methods to create and manage the audit entries. The advantage here being the exchange is readily available with all the data involved to store in the database table.
#Component
public abstract class ProcessorAbstractTracker implements Processor {
#Override
abstract public void process(Exchange exchange) throws Exception;
public void createTracker ( Exchange exchange ) {
}
public void updateTracker ( Exchange exchange, String theResultsMessage, String theResultsStep ) {
}
}
Set an #Autowired Bean that every tracked Camel Processor wires in and put the tracking logic in the bean. This seems to be simple and clean. My only concern/question here is how to scope the bean (maybe prototype)...since there would be many routes utilizing the bean concurrently, is there any chance we get mixed processing values...
#Autowired
ProcessorTracker tracker;
Other ideas?
tia, adym

DDD: Where to raise "created" domain event

I struggle to find and implement the best practise for the following problem: where is the best location to raise create domain event (the event that notifies for the creation of an aggregate). For example if we have Order aggregate in our bounded context we would like to notifie all interested parties when order is create. The event could be OrderCreatedEvent.
What I tried in first place is to raise this event in the constructor (I have a collection of domain events in each aggregate). This way it is okay only when we create the order. Because when we would like to do anything with this aggregate in the future we are going to create new instance of it through the constructor. Then OrderCreatedEvent will be raised again but it is not true.
However, I thought it would be okey to raise the event in the application layer but it is an anti-pattern (the domain events should live only in the domain). Maybe to have a method Create that will just add the OrderCreatedEvent to its domain events list and call it in the application layer when order is created is an option.
Interesting fact I found on the internet is that it is an anti-pattern to raise domain events in the contructor which means the last described option (to have Create method) would be the best approach.
I am using Spring Boot for the application and MapStruct for the mapper that maps the database/repository Entity to the domain model aggregate. Also, tried to find a way to create a mapper that is going to skip the contructor of the target class but as all properties of the Order aggregate are private seems impossible.
Usually constructor are used only to make assignations on object's fields. This is not the right place to trigger behaviours, especially when they throw exceptions or have side effects
DDD theorists (from Eric Evans onwards) suggest implementing factories for aggregates creation. A factory method, for example, can invoke aggregate constructor (and wire up the aggregate with child domain objects as well) and also register an event.
Publishing events from the application layer is not an anti-pattern per se. Application services can depend from the domain events publisher, the important thing is that it's not application layer to decide which event to send
To summarize, with a stack like Java Spring Boot and domain events support, your code could look like
public class MyAggregate extends AbstractAggregateRoot {
public static MyAggregate create() {
MyAggregate created = new MyAggregate();
created.registerEvent(new MyAggregateCreated());
return created;
}
}
public class MyApplicationService {
#Autowired private MyAggregateRepository repository;
public void createAnAggregate() {
repository.save(MyAggregate.create());
}
}
notice that event publishing happens automagically after calling repository.save(). The downside here is that, when you use db-generated identifiers, aggregate id is not avaliable in the event payload since it's associated after persisting the aggregate. If i will change the application service code like that:
public class MyApplicationService {
#Autowired private MyAggregateRepository repository;
#Autowired private ApplicationEventPublisher publisher;
public void createAnAggregate() {
repository.save(MyAggregate.create()).domainEvents().forEach(evt -> {
publisher.publish(evt);
});
}
}
Application layer is in charge to decide what to do to fulfill this workflow (create an aggregate, persist it and send some event) but all the steps happen transparently. I can add a new property to the aggregate root, change DBMS or change event contract, this won't change these lines of code. Application layer decides what to do and domain layer decides how to do it. Factories are part of the domain layer, events are a transient part of the aggregate state and the publishing part is transparent from domain standpoint
Check out this question!
Is it safe to publish Domain Event before persisting the Aggregate?.
However, I thought it would be okey to raise the event in the application layer but it is an anti-pattern (the domain events should live only in the domain). - Domain events live in Domain layer, but Application layer references Domain layer and can easily emit domain events.

Spring service with in-memory list

I want to have a service which keeps a list inmemory so I don't need to access the database everytime. The service is accessed by a controller. Is this a valid approach or am I missing something? What about concurrent access here (from the controller)? Is this (stateful service) an anti-pattern?
#Service
public class ServiceCached {
private List<SomeObject> someObjects;
#PostConstruct
public void initOnce() {
someObjects = /** longer running loading methodd **/
}
public List<SomeObject> retrieveObjects() {
return someObjects;
}
}
Thanks!
I wouldn't call it an anti-pattern, but in my opinion loading the list from the database in a #PostConstruct method is not a good idea as you slow down the start up of your application, I'd rather use a lazy loading mechanism, but this would potentially introduce some concurrent access issues that would need to be handled.
In your example concurrent access from the controller should not be a problem as the list is loaded from a #PostConstruct method and the controller would depend on this service, therefore this service would need to be fully constructed before it is injected into the controller, therefore the list would already be loaded.
Preferably I'd suggest using Spring Caching: Caching Data with Spring, Documentation, Useful guide
Usage example:
#Cacheable("books")
public Book getByIsbn(String isbn) {
simulateSlowService();
return new Book(isbn, "Some book");
}
This way you do not need to take care of loading and evicting the objects. Once set up, the caching framework will take care of this for you.

Keep record of what users do in Spring MVC

I have a very large application written in Spring MVC. I want to keep an "activity record" that tracks into a database what users do in my application.
In the first stage I just want an activity log, it can be just a list of the controller methods that get called during user's actions, but later on I would like this info to be more "human readable", i.e. instead of "modifyAccount(accountId = 5, accountBalance =500) something like "user X updates balance for account 5 to 500".
The problem I see is, since my application is very large, I would not like to modify each of my actions to add this logging mechanism. Is there a more flexible, declarative way to do this?
You can make use of Aspect Oriented Programming (AOP) to automate the logging.
http://static.springsource.org/spring/docs/2.0.8/reference/aop.html
In the above page shows many examples on how to use AOP with spring. One example is the use of annotations to find methods you're interested in. The use of such annotation is an easy way to determine what methods should be logged.
The #Audit annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Auditable {
...
}
The auditing method
#After("#annotation(auditable)", argNames="joinPoint")
public void audit(JoinPoint joinPoint) {
logger.info("Called {} with arguments {}",
joinPoint.getSignature().getLongString(), joinPoint.getArgs());
}
I did not test this code but it gets the point across.

Resources