Add a dynamically created element to a REST API in Springboot - spring

I am trying to create a database that will hold the prices of assets that are obtained from exchanges. I've created an Exchange class that holds variables that are the various prices. In my code, I have the following:
try{
Exchange Coinbase = new Exchange();
Coinbase.setName("Coinbase");
Coinbase.setBtcBuy(priceRequestCoinbase(btcBuy));
Coinbase.setBtcSell(priceRequestCoinbase(btcSell));
Coinbase.setEthBuy(priceRequestCoinbase(ethBuy));
Coinbase.setEthSell(priceRequestCoinbase(ethSell));
I am now just struggling to figure out how I would add this to my database so that it is accessible through api calls later on.

You can always convert this as a json string using objectmapper and store as text / json in your DB. The api can return this and directly convert to your exchange object.
Adding:
Better way would be to have an exchange table with your field names as columns. Create a repository class implementing jparepository for your exchange object. Annotate your exchange object with #entity annotation and autogenerated Id. Use the inbuilt jpa save method to save to db.
Also by Java standards the variable names should start with a lowercase (coinbase)

Related

How can I register a custom object deserializer to the repository?

In String Boot backend,
I have a Vehicle class.
Classes like Bike, Car, Bus will extend class Vehicle.
On firestore database, I store instances of Vehicle including Bike, Car, etc.... So I expect to get a collection of these documents to a String Boot backend using the Spring Data FirestoreReactiveRepository and the return type will be Vehicle? I guess. How can I register an object deserializer to this repository to get the correct object of correct type from firestore.
I have no idea how to do it, because the document barely mention it.
Currently, I just use firestore library, not Spring Data one, to retrieve data as HashMap then convert it to object using registered objectmapper.

Spring data JPA save() return less/incorrect child and parent association mapping fields [duplicate]

I'm developing a RESTful webservice with spring-data as its data access layer, backed by JPA/Hibernate.
It is very common to have relationships between domain entities. For example, imagine an entity Product which has a Category entity.
Now, when the client POSTs a Product representation to a JAX-RS method. That method is annotated with #Transactional to wrap every repository operation in a transaction. Of course, the client only sends the id of an already existing Category, not the whole representation, just a reference (the foreign key).
In that method, if I do this:
entity = repository.save(entity);
the variable entity now has a Category with only the id field set. This didn't surprise me. I wasn't expecting a save (SQL insert) to retrieve information on related objects. But I need the whole Product object and related entities to be able to return to the user.
Then I did this:
entity = repository.save(entity);
entity = repository.findOne(entity.getId());
that is, retrieve the object after persisting it, within the same transaction/session.
To my surprise, the variable entity didn't change anything. Actually, the database didn't even get a single select query.
This is related with Hibernate's cache. For some reason, when in the same transaction, a find does not retrieve the whole object graph if that object was previously persisted.
With Hibernate, the solution appears to be to use session.refresh(entity) (see this and this). Makes sense.
But how can I achieve this with spring data?
I would like to avoid to create repetitive custom repositories. I think that this functionality should be a part of spring data itslef (Some people already reported this in spring data's forum: thread1, thread2).
tl;dr
References between entities in the web layer need to be made explicit by using links and should not be hidden behind semi-populated object instances. References in the persistence layer are represented by object references. So there should be a dedicated step transforming one (the link) into the other (the fully populated object reference).
Details
It's an anti-pattern to hand around backend ids as such and assume the marshaling binding doing the right thing. So the clients should rather work with links and hand those to the server to indicate they want to establish a connection between an already existing resource and one about to be created.
So assuming you have the existing Category exposed via /categories/4711, you could post to your server:
POST /products
{ links : [ { rel : "category", href : "/categories/4711" } ],
// further product data
}
The server would the instantiate a new Product instance, populate it with additional data and eventually populate the associations as follows:
Identify properties to be populated by looking up the link relation types (e.g. the category property here.
Extract the backend identifier from the given URI
Use the according repository to lookup the related entity instance
Set it on the root entity
So in your example boiling down to:
Product product = new Product();
// populate primitive properties
product.setCategory(categoryRepository.findOne(4711));
productRepository.save(product);
Simply posting something like this to the server:
POST /products
{ category : {
id : 1, … },
…
}
is suboptimal for a lot of reasons:
You want the persistence provider to implicitly persist a Product instance and at the same time 'recognize' that the Category instance referred to (actually consisting of an id only) is not meant to be persisted but updated with the data of the already existing Category? That's quite a bit of magic I'd argue.
You essentially impose the data structure you use to POST to the server to the persistence layer by expecting it to transparently deal with the way you decided to do POSTs. That's not a responsibility of the persistence layer but the web layer. The whole purpose of a web layer is to mitigate between the characteristics of an HTTP based protocol using representations and links to a backend service.

Which way is better when insert a record to the database using id generator?

Because my project may be adapted to mysql or oracle,so I have a method that to produce id .When insert a new student record, the student record should call the method to produce the id. But what I'm curious about is when to call the method.Now my project is build by spring cloud. I should call the method in service module and pass the student object with id to the dao module. Or I pass the student object and the in the dao module,I call the id generator?
Which way is better?
Ok, i've decided to extend my comment.
In my opinion a better way would be to generate id inside dao, because you need id to save object in database, so you have to be sure that id is generated. For example if you have multiple clients and each client can save to database object student it would be difficult to make sure that each client uses id generator method in proper way. If you would use this method you don't need to take care about validation of id.
Moreover generating id inside dao follow low coupling principle.

How to use Hazelcast with MapStore

I am using Hazelcast as caching Solution for my application.
My application has few inserts and updates to the database and these needs to be synced to Cache also.
I want to use MapStore functionality so that when I do IMap.put(), Hazelcast takes care of persisting the Object in underlying Db and also update its cache.
In the overridden store implementation, I want to call my DAO in following way to persist the Data.
public void store(Long key, Product value)
{
log.info("Storing Data for Employee {} in Database using DataStore ", value);
Long employeeId = employeeDao.create(value);
value.setId(employeeId );
}
There are few issues listed below:-
1) In put call, I want to use "key" as the "employeeId", but this is generated only after insertion happens for this record in the Db. So how do I put into the Cache when I don't have the Id.? I want Hazelcast to use the "id" generated as part of store method call (or any other way) as the key to my Object.
Imap.put(key,new Employee("name_of_Employee","age_of_employee"))
2) The MapStore implementation's store method returns a void so I cannot return the Id generated for this Object to the Client. How can I achieve this?
I tried using MapEntryListeners on the Map but the entry added callback does not return new Object. I also added PostProcessingMapStore interface to my MapStore but could not get the new Value back to client.
Please advice
You have 2 options:
1) Generate the employeeId outside of the database. You can use the IdGenerator from Hazelcast to do this.
2) If you must let the database generate the id, then you need to put the Employee in the cache manually AFTER it has been stored in the database.

How do you expose a Web API OData service that returns a combination of Entity Framework and File System results?

For example, I have a database table that contains the following fields:
ID
Type
FilePath
An Entity Framework model is created for that table. The model is used to create an EDM for an OData service.
I would like to use that Odata service to filter the database fields as well as filter the results based on the content of the files located at the file path.
For example I'd like to be able to use syntax like this to get all records where the Type starts with the word 'procedure' and the content contains the word 'test':
$filter=startswith(Type,'procedure') and substringof('test', FileContent)
I would like the database filters to be applied first so that there are less FileContents to read. I would also like to read the FileContents one by one using a stream instead of loading them all into memory.
Can this be accomplished through LINQ by creating some sort of IQueryable object?
Can this be accomplished through Web API OData by attaching a property to the EDM and treating it differently?
It may be resolved in this way:
Add a property, say Content to the entity type.
Derive ODataQueryOptions and overwrite its ApplyTo method. This is the base class:
https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Http.OData/OData/Query/ODataQueryOptions.cs
Use the derived class in the controller:
public XXXXXController
{
public IHttpActionResult(MyODataQueryOptions options)
{
var products = this.GetProducts().AsQueryable();
return Ok(options.ApplyTo(products));
}
}

Resources