Store data in BEAN (Spring Boot REST) - spring

I am creating a REST API with Spring Boot. Most of the data come from a database but some data is fetched from third-party APIs. The problem is some of them have access limitations like max 10 requests per minute or something.
Now I am looking for a method to cache the data in my spring application and only update it every few seconds. Storing it in the db and updating it every 10 seconds is a little bit too much since the fetched data is about 1000 rows. So I thought I simply store it in my service bean.
This is my approach so far. (Coded in Kotlin)
#Service
class MyService(){
var myData: CustomDataObject
fun getData() = myData
fun updateData(){
// call API and store in myData Object
}
}
It works but it seems kinda hacky to me. Not really a clean solution, is it?
If someone has a better approach to this I would be very thankful.

Well, for me the answer is pretty obvious: use Spring Cache.

Related

Make sure that data is loaded before the application startup | Spring webflux

I have a spring webflux application.
I am loading some list from database into bean. I have two ways of implementing the loading of this bean.
Approach 1: Reactive Way
#Bean
public List<Item> getItemList() throws IOException {
List<Item> itemList = new ArrayList<>();
itemRespository.findAll().collectList().subscribe(itemList::addAll);
return itemList;
}
Approach 2 : Blocking way
#Bean
public List<Item> getItemList() throws IOException {
List<Item> itemList = itemRespository.findAll().collectList().block();
return itemList;
}
Now as I want my application to be reactive, I don't want to use the blocking way.
But the endpoints which I am exposing through my controller depends on this bean's data.
#RestController
public class SomeController{
#Autowired
private List<items> getItemList;
#GetMapping('/endpoint')
public void process(){
List list = getItemList; //this may not get initialzed as the bean loading is reactive
//some more code
}
}
So in case of reactive approach, it may happen that somebody may call my endpoint(as application has already started and ready to serve requests), while due to some reason it may happened that my list has yet not bean retrieved from database(may be any reason ex: slowness of database server etc.), producing inconsistent results for the users calling my endpoint(which in turns depend on this bean).
I am looking for a solution for this scenario.
EDIT : More precise question is that should I load those beans reactively in my application, on which my exposed endpoints are dependent?
The current application architecture solution presented is a typical example on a design that is inherently blocking.
If the first request made to the api needs the items to be in place, then we must sure that they are there before we can take on requests. And the only way to ensure that is to block until the items de facto have been fetched and stored.
Since the design is inherently blocking, we need to rethink our approach.
What we want is to make the service available for requests as quick as possible. We can solve this by using a cache, that will get filled when the first request is made.
Which means application starts up with an empty cache. This cache could for instance be a #Component as spring beans are singletons by default.
the steps would be:
service starts up, cache is empty
service receives its first request
checks if there is data in the cache
if data is stale, evict the cache
if cache is empty, fetch the data from our source
fill the cache with our fetched data
set a ttl (time to live) on the data placed in the cache
return the data to the calling client
Second request:
request comes in to the service
checks if there is data in the cache
checks if the data is stale
if not grab the data and return it to the calling subscriber
There are several cache solutions out there, spring has their #Cachable annotation, which by default is just a key value store, but can be paired with an external solution like redis etc.
Other solutions can be Google guava which has a very good read on their github.
This type of solution is called trading memory for cpu we gain startup time and fast requests (cpu), but the cost is we will spend some more memory to hold data in a cache.

Transaction issue when DB Call happens after Rest Call

I am using Spring Boot and my application is just Monolithic for now, may switch to microservices later.
SCENARIO 1: Here My DB call Does NOT depend on REST Response
#Transactional
class MyService {
public void DBCallNotDependsOnRESTResponse(){
//DB Call
//REST Call, This restcall gives response like 200 "successfull"
}
}
SCENARIO 2: Here My DB call depends on REST Response
#Transactional
class MyService {
public void DBCallDependsOnRESTResponse(){
//REST Call, making a Real Transaction using BrainTree
//DB Call, HERE DB CALL DEPENDS ON REST RESPONSE
}
}
In case of Scenario 1, I have no issues as DB gets rolled back incase REST fails.
BUT, incase of Scenario 2, REST call cannot be rolled back, incase if any exception occurs at DB call.
I already searched in google for above, I found some solutions like we need to use something like Pub-Sub model system seems, BUT I could not able to get that concept to my head clearly.
I will be glad if someone could able to provide solution for SCENARIO 2. How Other Ecommerce businesses handling their transactions effectively, I guess my query related to some Architecture design.. Please advice some good architecture approach to solve above Transaction issue. Do you think using some Messaging system like Kafka will solve above issue..? FYI, currently, my application is Monolithic, shall I use Microservices? Do I need to use two-phase-commit or Sagas will solve my problem? Does Sagas can be used for Monolithic application?
EDIT:
Regarding RestCall: I am actually making a Real Transaction using BrainTree, which is a Rest Call.
Can you elaborate what are you achieving from rest call? Are you updating any data that will be used by the DB call?
If the 2 calls are independent, will the order be of importance? Since db call will be committed at the end of method itself

Reactive streaming approach of file upload in Spring (Boot)

We have spent a lot of hours on the inet and on stackoverflow, but none of the findings satisfied us in the way we planned a file upload in Spring context.
A few words towards our architecture. We have a node.js client which uploads files into a Spring Boot app. Let us call this REST endpoint our "client endpoint". Our Spring Boot application acts as middleware and calls endpoints of a "foreign system", so we call this endpoint a "foreign" one, due to distinction. The main purpose is the file handling between these two endpoints and some business logic in between.
Actually, the interface to our client looks like this:
public class FileDO {
private String id;
private byte[] file;
...
}
Here we are very flexible because it is our client and our interface defintion.
Due to the issue that under load our system has run out of memory sometimes, we plan to reorganize our code into a more stream-based, reactive approach. When i write "under load", i mean heavily under load, e.g. hundreds of file uploads at the same time with big files from at least some MB to at most 1GB. We know, that this tests don't represent real applications use cases, but we want to be prepared.
We spent some research into our challenge and we ended up with profiler tools showing us that according to our REST endpoints we store the files as byte arrays completely in our memory. Thats all, but not efficient.
Currently we are facing this requirement to deliver a REST endpoint for file upload and push these files into another REST endpoint of some foreign system. Doing so, our main applications intention is to be some middle tier for file upload. According to this initial situation we are looking forward to not have those files as a whole in our memory. Best would be a stream, maybe reactive. We are partially reactive with some business functions already, but at the very beginning of being familiar with all that stuff.
So, what are our steps so far? We introduced a new Client (node.js --> Spring Boot) interface as the following one. This works so far. But is it really a stream based approach? First metrics have shown, that this doesn't reduce memory utilization.
#PostMapping(value="/uploadFile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
#ResponseStatus(HttpStatus.CREATED)
public Mono<Void> upload(#RequestPart(name = "id") String id, #RequestPart(name = "file") Mono<FilePart> file) {
fileService.save(id, file);
...
}
First question: is this type Mono<> right here? Or should we better have Flux of DataBuffer or something? And, if so, how the client shoud behave and deliver data in such a format that it is really a streaming approach?
The FileService class then should post this file(s) into the foreign system, perhaps do something else with given data, at least log the id and the file name. :-)
Our code in this FileService.save(..) actually looks like the following in between:
...
MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
bodyBuilder.asyncPart(...take mono somehow...);
bodyBuilder.part("id", id);
return webClient.create("url-of-foreign-system")
.uri("/uploadFile")
.syncBody(bodyBuilder.build())
.retrieve()
.bodyToMono(Result.class);
...
Unfortunately, the second REST endpoint, the one of our foreign system, looks little different to our first one. It will be enriched by data from another system. It takes some FileDO2 with an id and a byte array and some other meta data specific to the second foreign system.
As said, our approach should be to minimize the memory footprint of the actions in between client and foreign system. Sometimes we have not only to deliver data to that system, but also do some business logic that maybe slows down the whole streaming process.
Any ideas to do that in a whole? Currently we have not clue to do that all...
We appreciate any help or ideas.

Spring Data Cassandra gigabytes of data findAll() approach

I know this has been asked before, but Spring Data is growing a lot with time.
How would you implement a findAll() that returns millions of rows?
I know Spring Data has stream API, even though I'm not exactly sure if it would be safe with so much data. From my understanding, this is not going to retrieve all data at once, but while processing it.
Stream<T> streamAllBy...(...);
Also, a second approach would be this, only downside would be that I have to deal manually with pagination.
Slice<T> findAllBy...(..., Pageable pageable)
Any ideas?
Declaring Stream<T> as a return type for a query method is indeed the preferred approach. The repository layer adapts query execution to the declared type and performs transparent forward-pagination while consuming the stream.
Spring Data's repository approach requires certain method signatures, that might be not practical in each scenario.

ZK binder updating lists slow

For some time I have been working with ZK and now I have an application hosted in the cloud but this does not meet my performance expectations. My application uses ZK for the view, Hibernate for the interaction with the MySQL database and Spring for the management of beans related to database interaction.
Example scenario:
At initialization a list is retrieved from the database using hibernate (we are talking about max 200 objects, max 6 standard attributes). This takes some time, but is acceptable.
I add or delete objects from the list I use #NotifyChange("list") to tell the view that the list has changed.
The list is updated but this takes long, in my opinion (~2 seconds)
Step 3 takes about as long as step 1 which I don't understand, the Spring managed objects for database interaction have yet been initialized. Another thing to note is that I don't reload the entire list from the database when adding or deleting an object from the list; A local copy is kept of the objects in the spring managed bean #Autowired to my ViewModels. (Yes, potentially out of sync with the database, but in my case not much of an issue) But this eliminates hibernate/spring/database as the bottleneck, right?.
Also I ran this on the localhost, and of course that is faster but still not instant as I would expect/want.
Now I thought that it might have to do something with the creation and deletion of objects in java related to lists. I did research on how the ZK binder works and how objects are updated but I can't find anything about how the binder handles updates on lists.
Does anyone know how the ZK binder updates a list in the view when in the viewmodel the method is annotated with #NotifyChange("listA") ? Does it actually throw away the old list and sets the whole new list, or does it somehow have a merge on differences?
Also comments on what else could be the bottleneck are very welcome!
Thanks in advance,
Robert
I assume you use Listbox to represent your list.
First you need to know, that zk uses the same data
structure for MVVM that it uses for MVC. This means
that it uses ListModel and the performance tips
are usefull for MVVM as well.
Of course zk can't implement the standart model
in a way, that it fits everybodys needs.
So what you have to do is implement your own
model. Usually the best is to extend from ListModelList.
This way you can smart update the list.
i work alot with ZK but i have never use #NotifyChange, when i want to reload the data of a grid or listbox I always render or load it all again. For me it works fine and fast in less than 1 second. Here is an example of my binding:
>
And yes, when the data changes i recall my method, load it again and works really fine.
#Listen("onCreate = #listboxSolicitudes")
public void loadList() {
List<ConsultasSolicitudes> listaConsulta = null;
listaConsulta = ConsultasSeguimientoDeSolicitudesDAO.obtenerSolicitudesAsignadas((Long) cbResponsable.getSelectedItem().getValue());
ListModelList<ConsultasSolicitudes> solModel = new ListModelList<ConsultasSolicitudes>(listaConsulta);
listboxSolicitudesAsignadas.setModel(solModel);
}
Maybe this can help you, but something must be wrong if it´s taking that long.

Resources