Post object using restController - java

I have small problem to create correctly mathod adding people to teams. The reason is my problem is that i can't add two arguments in requestbody (or PathVariable).
I want to take a person id and team id and return both connected. I create separated class where i generate id but i have problem to imput this correctly id from database:
This is my method in cotroller:
#PostMapping("/addPeopleToTeams/{teamId}/{personId}")
#ResponseBody
public String addPeopleToTeam(#RequestBody TeamsAndPersonsId teamsAndPersonsId){
System.out.println(" " + teamsAndPersonsId.getPersonId());
System.out.println(" " + teamsAndPersonsId.getTeamId());
teamService.findTeamById(teamsAndPersonsId.getTeamId());
personService.findById(teamsAndPersonsId.getPersonId());
return teamsAndPersonsId.getTeamId() + " " + teamsAndPersonsId.getPersonId();
}
This is my method find by id in service:
public Optional<TeamDto> findTeamById(Long id) {
Assert.notNull(id, "ID must exist ");
return teamRepository
.findById(id)
.map(p -> modelMapper.map(p, TeamDto.class));
}
Other my class is Team - this is entity, teamDto, and TeamsAndPersonsId.
TeamsAndPersonsId class:
public class TeamsAndPersonsId {
private Long personId;
private Long teamId;
public TeamsAndPersonsId(Long personId, Long teamId) {
this.personId = personId;
this.teamId = teamId;
}
public TeamsAndPersonsId(){}
public Long getPersonId() {
return personId;
}
public void setPersonId(Long personId) {
this.personId = personId;
}
public Long getTeamId() {
return teamId;
}
public void setTeamId(Long teamId) {
this.teamId = teamId;
}
How to correctly wrote this controller method to return real team and persons id? Like i add in surce:
#PostMapping("/addPeopleToTeams/{teamId}/{personId}"

You can actually use multiple path variables, use them to create a TeamsAndPersonsId , then keep the rest of your current code :
#PostMapping("/addPeopleToTeams/{teamId}/{personId}")
#ResponseBody
public String addPeopleToTeam(#PathVariable Long teamId, #PathVariable Long personId){
TeamsAndPersonsId teamsAndPersonsId = new TeamsAndPersonsId(teamId, personId);
// etc...

Related

org.springframework.dao.IncorrectResultSizeDataAccessException Mongo Limit dosen't work?

GoodEvening
i'm new about mongo, and i choose to use a mix & match of RepositoryPattern and Mongotemplate
Now i find a very strange error when i want to use MongoTemplate to retrive a specific value of an inner object in order to calculate a progressive ID
It seems my code work for 0 or 1 document inside a collection, but when i have equal or more than 2 documents, the method will throw a
org.springframework.dao.IncorrectResultSizeDataAccessException: Query { "$java" : Query: {}, Fields: {}, Sort: {} } returned non unique result.
as if limit dosen't work.
I have just, for now, a rest and a repository pattern, but in the service layer i have another autowire whit mongotemplate class, this template is used by just 1 method.
public DetailedOrder findTheBiggestBy(String byWhat){
Query query = new Query();
query.with(Sort.by(Sort.Direction.DESC,byWhat)).limit(1);
return mongoDb.findOne(query,DetailedOrder.class);
}
As you can see is pretty simple and it actually work, becouse before moving the Template inside Service it actually work whit various documents inside collection, when i autowired it over the rest layer.
There is something i miss and is not rly related to mongo but related to spring autowire?
My detailorderClass is
package com.service.backend.BK.Pojo;
import com.service.backend.BK.Constants.Constant;
import org.bson.codecs.pojo.annotations.BsonId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.FieldType;
import org.springframework.data.mongodb.core.mapping.MongoId;
import java.util.List;
#Document("Orders")
public class DetailedOrder {
#MongoId(FieldType.OBJECT_ID)
private String id;
#Field
private List<Integer> category;
// 1 junk to 10 Pristine
#Field
private Integer quality;
#Field
private BaseOrder baseOrder;
#Field
private String qualityDescription;
public DetailedOrder(){}
public DetailedOrder(String Description,Double price, List<Integer> category, Integer quality) {
this.category = category;
this.quality = quality;
this.qualityDescription = qualityDescriptionPairFactory(quality);
this.baseOrder=new BaseOrder(Description,price);
}
public List<Integer> getCategory() {
return category;
}
public void setCategory(List<Integer> category) {
this.category = category;
}
public Integer getQuality() {
return quality;
}
public void setQuality(Integer quality) {
this.quality = quality;
}
public String getQualityDescription() {
return qualityDescription;
}
public void setQualityDescription(String qualityDescription) {
this.qualityDescription = qualityDescription;}
private String qualityDescriptionPairFactory(int quality){
switch (quality){
case 1:return Constant.Quality.NOGRAD.label;
case 2:return Constant.Quality.HEAVYDMN.label;
case 3:return Constant.Quality.LOOSE.label;
case 4:return Constant.Quality.POOR.label;
case 5:return Constant.Quality.LIGHTDMN.label;
case 6:return Constant.Quality.GOOD.label;
case 7:return Constant.Quality.EXCELENT.label;
case 8:return Constant.Quality.NEARMINT.label;
case 9:return Constant.Quality.MINT.label;
case 10:return Constant.Quality.NEWUNRL.label;
default:return Constant.Quality.NOGRAD.label; }
}
#Override
public String toString() {
return "DetailedOrder{" +
"id='" + id + '\'' +
", baseOrder='" + getBaseOrder().returnBaseOrder() + '\'' +
", category=" + category +
", quality=" + quality +
", qualityDescription='" + qualityDescription + '\'' +
'}';
}
public BaseOrder getBaseOrder() {
return baseOrder;
}
public void setBaseOrder(BaseOrder baseOrder) {
this.baseOrder = baseOrder;
}
public void setId(String id) {
this.id = id;
}
}
and that lead to baseOrderClass
package com.service.backend.BK.Pojo;
import org.joda.time.DateTime;
import org.springframework.data.mongodb.core.mapping.Document;
public class BaseOrder {
private String id;
private String description;
private Double desideredPrice;
//Pending,active,Rejected,Hault,etc etc
private int status;
protected BaseOrder(){}
protected BaseOrder(String description, Double desideredPrice) {
this.description = description;
this.desideredPrice = desideredPrice;
}
public String returnBaseOrder(){
return "BaseOrder{" +
"id='" + id + '\'' +
", description='" + description + '\'' +
", desideredPrice=" + desideredPrice +
", status=" + status +
'}';
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getDesideredPrice() {
return desideredPrice;
}
public void setDesideredPrice(Double desideredPrice) {
this.desideredPrice = desideredPrice;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
//###############################################################################################################//
}
The OPs question related to a spring context issue. By just accessing the repository directly the problem could be resolved.
Within the comments an additional question/target has been found, i would like to provide an answer for that.
How to have persistence access within the domain layer?
I have created a repository at GitHub where you can find a working solution. This code is not best practice but will provide a solution that works.
Every constructed domain object needs access to the declared repositories. That can be a problem when using dependency injection. In order to keep entity construction pristine an abstract class has been introduces that takes the task to get the concrete repositories.
The core idea is to make the Spring ApplicationContext accessable statically. Having this context an access to the repositories is just one call away.
Beans having the ApplicationContextAware interface will be called in a very early stage of Spring Boots startup. When using this class to access the context every consumer has to call it after Spring has been loaded. This can be achieved by using #Component, #Configuration, #Bean to run code and there will be no race condition.
Further details are within the repositories readme file.
I hope that this helps you :)

How to get specified fields from the Object, to check if List contains() Object? Room booking validaton problem

Here is my entity:
#Entity
#Table(name = "reservation")
public class Reservation {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "date_in")
private LocalDate dateIn;
#Column(name = "date_out")
private LocalDate dateOut;
#ManyToOne
private Guest guest;
#ManyToOne
private Room room;
public Reservation() {
}
public Reservation(LocalDate dateIn, LocalDate dateOut, Guest guest, Room room) {
this.dateIn = dateIn;
this.dateOut = dateOut;
this.guest = guest;
this.room = room;
}
public Guest getGuest() {
return guest;
}
public void setGuest(Guest guest) {
this.guest = guest;
}
public Room getRoom() {
return room;
}
public void setRoom(Room room) {
this.room = room;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public LocalDate getDateIn() {
return dateIn;
}
public void setDateIn(LocalDate dateIn) {
this.dateIn = dateIn;
}
public LocalDate getDateOut() {
return dateOut;
}
public void setDateOut(LocalDate dateOut) {
this.dateOut = dateOut;
}
#Override
public String toString() {
return "Reservation{" +
"id=" + id +
", dateIn=" + dateIn +
", dateOut=" + dateOut +
", guest=" + guest +
", room=" + room +
'}';
}
}
Here is my validation method:
#Override
public Reservation save(Reservation reservation) {
validateDate(reservation.getDateIn(), reservation.getDateOut());
List<ReservationRepository> bookedRooms = reservationRepository.findBookedRooms();
if (!bookedRooms.contains(reservation)) {
return reservationRepository.save(reservation);
}
return null;
}
findBookedRooms() gets this sql query:
#Query(value = "SELECT rs.room_id, rs.date_in, rs.date_out FROM reservation rs LEFT JOIN room r ON rs.room_id = r.id WHERE rs.id IS NOT NULL", nativeQuery = true)
List<ReservationRepository> findBookedRooms();
PROBLEM:
In if statement bookedRooms gets List of:reservation.room_id, reservation.date_in, reservation.date_out parameters, whereas reservation Object gets:reservation.id,reservation.date_in, reservation.date_out.
In consequence we've got rs.room_id - rs.id conflict, so "if statement" will always be true.How can I make my reservation object to get these specific parameters:reservation.getRoom().getNumber(), reservation.date_in,
reservation.date_out?
I need this validation to check if there is no conflict in dates while booking specific room.
Your validation consists in using the contains method from the list retrieved from the DB, checking: "the list contains this reservation?".
Your question basically says that the IF statement is always evaluating to true, so it's always evaluating to: "this reservation is not in the list!"
Considering all this, I believe you should check how the contains method in the List interface works. This post has some insight on it.
The contains method uses the equals method to check if a object has an equal object in the list. Since both types used are different (ReservationRepository is not the same as Reservation) it will fail 100% of the time, unless you start overriding the equals method (considering you are using two types for comparison, I would warn you, don't do that).
Possible solution:
Loop through the list and inside the loop check the fields that are needed to evaluate if the Reservation already exists in tour DB. Do it inside your save method, or write another method for better code organization.
The loop would probably look like this:
boolean reservationExists = false;
for(ReservationRepository r:bookedRooms){
if (r.getRoom().equals(reservation.getRoom()) &&
r.getDateOut().equals(reservation.getDateOut()) &&
r.getDateIn().equals(reservation.getDateIn())) {
reservationExists = true;
break;
}
}

Cannot POST A COLUMN RESTFUL API

I have made restful API Using java hibernate jersery Framework.
I have to post data I have done it but I'm missing with one of the column that is MealTypeName.
Here is my DAO Class:
public class MealTypeDAO {
public void addMealType( MealType bean) {
Session session = SessionUtil.getSession();
Transaction tx = session.beginTransaction();
addMealType(session, bean);
tx.commit();
session.close();
}
private void addMealType(Session session, MealType bean){
MealType mealType = new MealType();
mealType.setMealTypename(bean.getMealTypename());
mealType.setModifiedon(bean.getModifiedon());
mealType.setModifiedby(bean.getModifiedby());
session.save(mealType);
}
Here is my resource class:
public class MealTypeResource {
#POST
#Path("/create")
#Consumes("application/json")
public Response addMealType(MealType meal){
meal.setMealTypename(meal.getMealTypename());
meal.setModifiedon(meal.getModifiedon());
meal.setModifiedby(meal.getModifiedby());
MealTypeDAO dao = new MealTypeDAO();
dao.addMealType(meal);
return Response.ok().build();
}
#GET
#Produces("application/json")
public Response getMealType() {
MealTypeDAO dao = new MealTypeDAO();
List mealTypes = dao.getMealType();
String json = new Gson().toJson(mealTypes);
return Response.ok().entity(json.toString()).build();
}
This is my entity class:
public class MealType {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int MealTypeId;
#Column
private String MealTypename;
#Column
private int modifiedby;
#Column
private String modifiedon;
public int getMealTypeId() {
return MealTypeId;
}
public void setMealTypeId(int mealTypeId) {
MealTypeId = mealTypeId;
}
public String getMealTypename() {
return MealTypename;
}
public void setMealTypename(String mealTypename) {
MealTypename = mealTypename;
}
public int getModifiedby() {
return modifiedby;
}
public void setModifiedby(int modifiedby) {
this.modifiedby = modifiedby;
}
public String getModifiedon() {
return modifiedon;
}
public void setModifiedon(String modifiedon) {
this.modifiedon = modifiedon;
}
MySQL DB:
CREATE TABLE `mealtype`(`Mealtypeid` int(11) NOT NULL AUTO_INCREMENT,`MealTypename` varchar(20) DEFAULT NULL,`modifiedby` int(11) NOT NULL,`modifiedon` datetime NOT NULL,PRIMARY KEY (`Mealtypeid`)) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
Now M posting these data in JSON FORMAT From POSTMAN:
{"MealTypeId":14,"MealTypename":"adsdf","modifiedby":1,"modifiedon":"2000-01-01 00:00:00"}
And M getting these data:
{"MealTypeId":14,"modifiedby":1,"modifiedon":"2000-01-01 00:00:00"}
MealTypename is missing. How so? Can someone help me out?
You are using names with the first letter in the upper case MealTypename — this is a reason.
The getter with name getMealTypename is used for a JSON property mealTypename (not MealTypename):
public String getMealTypename() {
return MealTypename;
}
You need to specify a JSON property name:
#JsonProperty("MealTypename") — for Jackson
#SerializedName("MealTypename") — for Gson
You need to put this annotation to the field or getter of the class which you mapping to JSON (MealType).
And use the standard Java naming convention.
public class MealType {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int mealTypeId;
#Column
private String mealTypename;
}
And this looks really strange:
meal.setMealTypename(meal.getMealTypename());
meal.setModifiedon(meal.getModifiedon());
meal.setModifiedby(meal.getModifiedby());

Cassandra partition key parts are missing

I'm following the Cassandra java object mapper tutorial on Datastax website.
and while defining accessors
#Query("SELECT * FROM testks.user ")
Result<User> getAll();
running this query give me a
com.datastax.driver.core.exceptions.InvalidQueryException: Some partition key parts are missing: id
Looking around it seems that you cannot query in cassandra without providing a partition key. Is that the case? This seems like a strange requirement. If I want a select all query, how would I go about doing that?
the table is defined as
CREATE TABLE testks.user (
id text PRIMARY KEY,
name text
)
You didn't provide many details. if you follow these below steps you shouldn't get any error
You should define the user model like below
User.java
#Table(name = "user")
public class User {
#PartitionKey
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "User{" + "id=" + id + ", name=" + name + '}';
}
}
And Repository like below
UserAccessor.java
#Accessor
public interface UserAccessor {
#Query("SELECT * FROM user")
Result<User> getAll();
}
Here is how you can use the repository
Main.Java
public static void main(String[] args) {
try (Cluster cluster = Cluster.builder().addContactPoints("127.0.0.1").withCredentials("cassandra", "cassandra").build(); Session session = cluster.connect("test")) {
MappingManager manager = new MappingManager(session);
UserAccessor userAccessor = manager.createAccessor(UserAccessor.class);
System.out.println(userAccessor.getAll().all());
}
}

java cassandra object mapping annotations

Can you provide an example for mapping collections using datastax api annotations to use Map.
class pojo {
#PartitionKey(value = 0)
#Column(name = "user_id")
String userId;
#Column(name = "attributes")
// How to map it
Map<String, String> attributes;
}
error log :
2015-08-03 16:33:34,568 INFO com.jpma.jpmc.slot.persistance.DAOFactory main - Cassandra Cluster Details: ConnectionCfg [userName=test, password=test, port=9042, seeds=[Ljava.lang.String;#1a85bd75, keySpace=test]
java.lang.Class
2015-08-03 16:33:34,646 DEBUG com.datastax.driver.mapping.EntityMapper main - Preparing query INSERT INTO "test"."user_event_date"("user_id","entry_date","entry_time","app","attributes","user_ip","user_authschemes") VALUES (?,?,?,?,?,?,?);
com.datastax.driver.core.exceptions.InvalidQueryException: Unknown identifier attributes
Based on the error message you are seeing, I'm guessing that attributes is not defined in your table definition. Would you mind editing your post with that?
But when I build my CQL table like this (note the compound partition key of itemid and version):
CREATE TABLE products.itemmaster (
itemid text,
version int,
productid uuid,
supplierskumap map<uuid, text>,
PRIMARY KEY ((itemid,version), productid)
);
...insert this row:
INSERT INTO products.itemmaster (itemid,version,productid,supplierskumap)
VALUES ('item1',1,26893749-dcfc-42c7-892c-bee8c9cff630,
{1351f82f-5dc5-4328-82f4-962429c92a2b:'86CCG123'});
...and I build my POJO like this:
#Table(keyspace = "products", name = "itemmaster")
public class Product {
#PartitionKey(0)
private String itemid;
#PartitionKey(1)
private int version;
#ClusteringColumn
private UUID productid;
#Column(name="supplierskumap")
private Map<UUID,String> suppliersku;
public UUID getProductid() {
return productid;
}
public void setProductid(UUID _productid) {
this.productid = _productid;
}
public int getVersion() {
return this.version;
}
public void setVersion(int _version)
{
this.version = _version;
}
public String getItemid() {
return itemid;
}
public void setItemid(String _itemid) {
this.itemid = _itemid;
}
public Map<UUID, String> getSuppliersku() {
return suppliersku;
}
public void setSuppliersku(Map<UUID, String> _suppliersku) {
this.suppliersku = _suppliersku;
}
}
...with this constructor and getProd method on my data access object (dao):
public ProductsDAO()
{
session = connect(CASSANDRA_NODES, USERNAME, PASSWORD);
prodMapper = new MappingManager(session).mapper(Product.class);
}
public Product getProd(String itemid, int version, UUID productid) {
return prodMapper.get(itemid,version,sku);
}
...then this main class successfully queries my table and maps my Map:
private static void main(String[] args) {
ProductsDAO dao = new ProductsDAO();
Product prod = dao.getProd("item1", 1, UUID.fromString("26893749-dcfc-42c7-892c-bee8c9cff630"));
System.out.println(
prod.getProductid() + " - " +
prod.getItemid() + " - " +
prod.getSuppliersku().get(UUID.fromString("1351f82f-5dc5-4328-82f4-962429c92a2b")));
dao.closeCassandra();
}
...and produces this output:
26893749-dcfc-42c7-892c-bee8c9cff630 - item1 - 86CCG123
NOTE: Edit made to the above example to support a compound partition key.

Categories