How to Use Mongo Pojos in Bulk Upsert - spring

Hi i have a list of Mongo Pojo I want to use upsert .I don't know how to use My pojo's .
#Test
public void testAgentDataStorage() {
AgentDataStorage a = new AgentDataStorage(124l);
DBCollection collection = mongoTemplate.getDb().getCollection("agent_data_storage");
BulkWriteOperation bulkWriteOperation = collection.initializeUnorderedBulkOperation();
BulkWriteRequestBuilder bulkWriteRequestBuilder = bulkWriteOperation.find((DBObject) a);
BulkUpdateRequestBuilder updateReq = bulkWriteRequestBuilder.upsert();
a.getDataPoints().put("TOTAL_INCENTIVE_EARNINGS" , 13);
updateReq.replaceOne((DBObject) a);
BulkWriteResult result = bulkWriteOperation.execute();
}
Here AgentDataStorage is my pojo and this code is giving error
AgentDataStorage cannot be cast to com.mongodb.DBObject .
Below is my AgentDataStorage
#CompoundIndex(name = "account_date_idx", def = "{'account' : 1, 'date' : 1}", unique = true)
#Document(collection = "agent_data_storage")
public class AgentDataStorage extends MongoKeyedEntity<String> implements Serializable {
public static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
#Field
private Long account;
#Field()
private String date;
#Field
private Map<String, Integer> dataPoints = new HashMap<>();
public AgentDataStorage(Long account) {
this.account = account;
this.date = dateFormat.format(new Date());
for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
this.dataPoints.put(dataPoint.toString(), 0);
}
}
public AgentDataStorage(String account) {
this.account = Long.valueOf(account);
for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
this.dataPoints.put(dataPoint.toString(), 0);
}
}
public AgentDataStorage(Long account, Date date) {
this.account = account;
this.date = dateFormat.format(date);
for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
this.dataPoints.put(dataPoint.toString(), 0);
}
}
public AgentDataStorage(Long account, Date date, Map<String, Integer> dataPoints) {
this.account = account;
this.date = dateFormat.format(date);
this.dataPoints = dataPoints;
}
public AgentDataStorage(String account, Date date) {
this.account = Long.valueOf(account);
this.date = dateFormat.format(date);
for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
this.dataPoints.put(dataPoint.toString(), 0);
}
}
public AgentDataStorage(String account, String date) {
this.account = Long.valueOf(account);
this.date = date;
for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
this.dataPoints.put(dataPoint.toString(), 0);
}
}
public Long getAccount() {
return account;
}
public void setAccount(Long account) {
this.account = account;
}
public Date getDate() throws ParseException {
return dateFormat.parse(this.date);
}
public void setDate(Date date) {
this.date = dateFormat.format(date);
}
public Map<String, Integer> getDataPoints() {
return dataPoints;
}
public void setDataPoints(Map<String, Integer> dataPoints) {
this.dataPoints = dataPoints;
}
public void updateDataPoint(AgentDataPoints agentDataPoints, Integer value) {
this.dataPoints.put(String.valueOf(agentDataPoints), value);
}

Mongo Java Driver doesn't have support for complex types and it looks like your pojos are annotated with spring mongo db annotation.
You've couple of options here MongoTemplate and MongoRepository.
MongoTemplate: http://docs.spring.io/spring-data/data-mongo/docs/1.10.0.M1/reference/html/#mongo-template
MongoRepository: http://docs.spring.io/spring-data/data-mongo/docs/1.10.0.M1/reference/html/#mongo.repositories

Related

Foregine key is not updating in spring boot Jpa

Basically, I am trying to establish a relationship between my two tables using spring boots.
And the relationship which I had used was the #onetoone and #onetomany relationship.
But after building the relationship and creating the table in MySQL whenever I run the program my foreign key is not updating.
The relationship is one user can have many contacts. I have tried unidirectional as well as bidirectional mapping but it is not working.
I want in contact table there will be a separate column for the foreign key. Based on that key I will show all contacts for that particular user.
This is my contact entity...
package com.example.jpa.contactEntities;
#Entity
#Table(name = "Contact")
public class ContactEntities {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long c_id;
private String c_name;
private String second_c_name;
private String c_work;
private String c_emali;
private String c_phone;
private String c_image;
#Column(length = 5000)
private String c_description;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "contact_id")
private UserEntities userEntities;
public ContactEntities() {
super();
}
public ContactEntities(long c_id, String c_name, String second_c_name, String c_work, String c_emali,
String c_phone, String c_image, String c_description, UserEntities userEntities) {
super();
this.c_id = c_id;
this.c_name = c_name;
this.second_c_name = second_c_name;
this.c_work = c_work;
this.c_emali = c_emali;
this.c_phone = c_phone;
this.c_image = c_image;
this.c_description = c_description;
this.userEntities = userEntities;
}
public long getC_id() {
return c_id;
}
public void setC_id(int c_id) {
this.c_id = c_id;
}
public String getC_name() {
return c_name;
}
public void setC_name(String c_name) {
this.c_name = c_name;
}
public String getSecond_c_name() {
return second_c_name;
}
public void setSecond_c_name(String second_c_name) {
this.second_c_name = second_c_name;
}
public String getC_work() {
return c_work;
}
public void setC_work(String c_work) {
this.c_work = c_work;
}
public String getC_emali() {
return c_emali;
}
public void setC_emali(String c_emali) {
this.c_emali = c_emali;
}
public String getC_phone() {
return c_phone;
}
public void setC_phone(String c_phone) {
this.c_phone = c_phone;
}
public String getC_image() {
return c_image;
}
public void setC_image(String c_image) {
this.c_image = c_image;
}
public String getC_description() {
return c_description;
}
public void setC_description(String c_description) {
this.c_description = c_description;
}
public UserEntities getUserEntities() {
return userEntities;
}
public void setUserEntities(UserEntities userEntities) {
this.userEntities = userEntities;
}
#Override
public String toString() {
return "ContactEntities [c_id=" + c_id + ", c_name=" + c_name + ", second_c_name=" + second_c_name + ", c_work="
+ c_work + ", c_emali=" + c_emali + ", c_phone=" + c_phone + ", c_image=" + c_image + ", c_description="
+ c_description + ", userEntities=" + userEntities + "]";
}
}
this is my user entity...
package com.example.jpa.userEntities;
#Entity
#Table(name = "UserEntities")
public class UserEntities {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long userId;
#NotBlank
#Size(min = 2, max = 20)
private String userName;
#NotBlank
#Column(unique = true)
#Email(regexp = "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$")
private String userEmail;
#NotNull(message = "password should not be blank")
private String userPass;
private boolean enable;
private String role;
#Column(length = 500)
private String userAbout;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "userEntities", orphanRemoval = true)
private List<ContactEntities> contactList = new ArrayList<>();
public UserEntities() {
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserEmail() {
return userEmail;
}
public void setUserEmail(String userEmail) {
this.userEmail = userEmail;
}
public String getUserPass() {
return userPass;
}
public void setUserPass(String userPass) {
this.userPass = userPass;
}
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public String getRoll() {
return role;
}
public void setRoll(String role) {
this.role = role;
}
public String getUserAbout() {
return userAbout;
}
public void setUserAbout(String userAbout) {
this.userAbout = userAbout;
}
public List<ContactEntities> getContactList() {
return contactList;
}
public void setContactList(List<ContactEntities> contactList) {
this.contactList = contactList;
}
#Override
public String toString() {
return "UserEntities [userId=" + userId + ", userName=" + userName + ", userEmail=" + userEmail + ", userPass="
+ userPass + ", enable=" + enable + ", role=" + role + ", userAbout=" + userAbout + ", contactList="
+ contactList + "]";
}
}
Repository of Contact
package com.example.jpa.repo;
import java.util.List;
import com.example.jpa.contactEntities.ContactEntities;
public interface ContactRepo extends JpaRepository<ContactEntities, Integer> {
#Query("from ContactEntities as c where c.userEntities.userId=:u_Id")
public List<ContactEntities> findContactsByUser(#Param("u_Id") long l);
}
Repository of User
package com.example.jpa.repo;
import com.example.jpa.userEntities.UserEntities;
#EnableJpaRepositories
public interface UserRepository extends JpaRepository<UserEntities, Integer> {
#Query("select u from UserEntities u where u.userEmail=:userEmail")
public UserEntities getUserByUserName(#Param("userEmail") String userEmail);
}
User controller
package com.example.jpa.controller;
#Controller
#RequestMapping("/user")
public class UserController {
#Autowired
private UserRepository userRepository;
#Autowired
private ContactRepo contactRepo;
#ModelAttribute
public void addCommonData(Model model, Principal principal) {
String username = principal.getName();
System.out.println("UserName:-" + username);
UserEntities userEntities = this.userRepository.getUserByUserName(username);
System.out.println("User:- " + userEntities);
model.addAttribute("userEntities", userEntities);
}
//dash board home
#RequestMapping("/index")
public String dashboard(Model model, Principal principal) {
return "normal/user_dashboard";
}
// open add form handler
#GetMapping("/add-contact")
public String openAddContactForm(Model model) {
model.addAttribute("title", "Add contact");
model.addAttribute("contactEntitie", new ContactEntities());
return "normal/add_contact";
}
// processing and contact form
#PostMapping("/upload")
public String processContact(#ModelAttribute ContactEntities contactEntitie,
#RequestParam("userImage") MultipartFile multipartFile, Principal principal, Model model,
HttpSession session) {
try {
model.addAttribute("contactEntitie", new ContactEntities());
String name = principal.getName();
UserEntities userEntities = userRepository.getUserByUserName(name);
userEntities.getContactList().add(contactEntitie);
// processing and uploading file....
if (multipartFile.isEmpty()) {
System.out.println("File is empty");
} else {
// upload the the file and update
contactEntitie.setC_image(multipartFile.getOriginalFilename());
File saveFile = new ClassPathResource("static/img").getFile();
// bring the folder path...
Path path = Paths
.get(saveFile.getAbsolutePath() + File.separator + multipartFile.getOriginalFilename());
Files.copy(multipartFile.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
System.out.println("Image is uploaded");
}
userRepository.save(userEntities);
System.out.println("Datas are :" + contactEntitie);
// message success
session.setAttribute("message", new Messages("Your Contact is added !!! Add more...", "success"));
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
e.printStackTrace();
// error message
session.setAttribute("message", new Messages("Something went wrong !!! Try Again", "danger"));
}
return "normal/add_contact";
}
// show Contact handler
#GetMapping("/show-contacts")
public String showContact(Model model, Principal principal) {
model.addAttribute("title", "Show Contacts");
String userName = principal.getName();
UserEntities userEntities = userRepository.getUserByUserName(userName);
List<ContactEntities> contactList = contactRepo.findContactsByUser(userEntities.getUserId());
model.addAttribute("contactList", contactList);
return "normal/show_contacts";
}
}
All configuration class
User Details configuration
package com.example.jpa.Myconfiguration;
public class UserDetailsServiceImple implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// fetching data from DB
UserEntities userEntities = userRepository.getUserByUserName(username);
if (userEntities == null) {
throw new UsernameNotFoundException("Could not found user !!!");
}
CustomUserDetails customUserDetails = new CustomUserDetails(userEntities);
return customUserDetails;
}
}
package com.example.jpa.Myconfiguration;
public class CustomUserDetails implements UserDetails {
private UserEntities userEntities;
public CustomUserDetails(UserEntities userEntities) {
super();
this.userEntities = userEntities;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(userEntities.getRoll());
return List.of(simpleGrantedAuthority);
}
#Override
public String getPassword() {
return userEntities.getUserPass();
}
#Override
public String getUsername() {
return userEntities.getUserEmail();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
Application property:-
#Database configuration
spring.datasource.url=jdbc:mysql://localhost:3306/smartcontact
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.NonRegisteringDriver
spring.jpa.properties.hibernate.dilact=org.hibernate.dialect.Mysql8Dialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
spring.servlet.multipart.enabled=true
spring.servlet.multipart.file-size-threshold=2KB
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB

DAO instance not working in service class - NullPointerException

In my spring boot project I created a Repository interface (which extends CRUDRepository) and an Entity class of the Table in my DB.
This is my Repo:
#Repository
public interface AuthPaymentDao extends CrudRepository<TFraudCard,String> {
#Query("SELECT t FROM TFraudCard t where t.tokenNumber = (?1)")
TFraudCard findByTokenNumber(String tokenNumber);
}
This is my Entity Class (TOKEN_NUMBER is the primary Key in the TFRAUDCARD TABLE):
#Entity
#Table(name = "TFRAUDCARD")
public class TFraudCard {
#Id
#Column(name="TOKEN_NUMBER")
private String tokenNumber;
#Column(name="TRANSACTIONNUMBER")
private int transactionNumber;
#Column(name="CARDNUMBER")
private int cardNumber;
#Column(name="DATEADDED", insertable = false, updatable = false, nullable = false)
private Timestamp dateAdded;
#Column(name="CALLINGENTITY", nullable = false)
private String callingEntity;
#Column(name="ACCOUNTID")
private String accountId;
#Column(name="ROUTINGNUMBER")
private String routingNumber;
#Column(name="BANKACCOUNTNUMBER")
private String bankAccountNumber;
#Column(name="COMMENTS")
private String comments;
#Column(name="USERID")
private String userId;
#Column(name="REMOVEDATE")
private Timestamp removeDate;
public String getTokenNumber() {
return tokenNumber;
}
public void setTokenNumber(String tokenNumber) {
this.tokenNumber = tokenNumber;
}
public int getTransactionNumber() {
return transactionNumber;
}
public void setTransactionNumber(int transactionNumber) {
this.transactionNumber = transactionNumber;
}
public int getCardNumber() {
return cardNumber;
}
public void setCardNumber(int cardNumber) {
this.cardNumber = cardNumber;
}
public Timestamp getDateAdded() {
return dateAdded;
}
public void setDateAdded(Timestamp dateAdded) {
this.dateAdded = dateAdded;
}
public String getCallingEntity() {
return callingEntity;
}
public void setCallingEntity(String callingEntity) {
this.callingEntity = callingEntity;
}
public String getAccountId() {
return accountId;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public String getRoutingNumber() {
return routingNumber;
}
public void setRoutingNumber(String routingNumber) {
this.routingNumber = routingNumber;
}
public String getBankAccountNumber() {
return bankAccountNumber;
}
public void setBankAccountNumber(String bankAccountNumber) {
this.bankAccountNumber = bankAccountNumber;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public Timestamp getRemoveDate() {
return removeDate;
}
public void setRemoveDate(Timestamp removeDate) {
this.removeDate = removeDate;
}
public TFraudCard() {
super();
}
public TFraudCard(String tokenNumber, int transactionNumber, int cardNumber, Timestamp dateAdded,
String callingEntity, String accountId, String routingNumber, String bankAccountNumber, String comments,
String userId, Timestamp removeDate) {
super();
this.tokenNumber = tokenNumber;
this.transactionNumber = transactionNumber;
this.cardNumber = cardNumber;
this.dateAdded = dateAdded;
this.callingEntity = callingEntity;
this.accountId = accountId;
this.routingNumber = routingNumber;
this.bankAccountNumber = bankAccountNumber;
this.comments = comments;
this.userId = userId;
this.removeDate = removeDate;
}
#Override
public String toString() {
return "TFraudCard [tokenNumber=" + tokenNumber + ", transactionNumber=" + transactionNumber + ", cardNumber="
+ cardNumber + ", dateAdded=" + dateAdded + ", callingEntity=" + callingEntity + ", accountId="
+ accountId + ", routingNumber=" + routingNumber + ", bankAccountNumber=" + bankAccountNumber
+ ", comments=" + comments + ", userId=" + userId + ", removeDate=" + removeDate + "]";
}
}
My Service Class:
Autowiring the DAO instance inside my Service Class:
Implementing the DAO instance inside a Method in the Service Class:
private void fraudCheck(PaymentDetail paymentDetail) throws RegularPaymentBusinessException {
logger.info("INSIDE FRAUD CHECK METHOD");
String pmtInd=paymentDetail.getPmtInd();
logger.info("pmtInd: " + pmtInd);
String tokenizedCardNum=paymentDetail.getTokenizedCardNum();
logger.info("tokenizedCardNum: " + tokenizedCardNum);
if(pmtInd.equalsIgnoreCase(VepsConstants.GIFT_CARD_IDENTIFIER) || pmtInd.equalsIgnoreCase(VepsConstants.CREDIT_CARD_IDENTIFIER) || pmtInd.equalsIgnoreCase(VepsConstants.DEBIT_CARD_IDENTIFIER)) {
logger.info("INSIDE CARD CHECK");
TFraudCard fraudCard = authPaymentDao.findByTokenNumber(tokenizedCardNum);
logger.info("fraudCard Details: " + fraudCard.toString());
if(fraudCard!=null) {
logger.info("INSIDE EXCEPTION FLOW FOR CARD FRAUD CHECK");
throw new RegularPaymentBusinessException(VepsConstants._9966, VepsConstants._9966_MESSAGE, VepsConstants.FAILURE);
}
}
}
Even though I pass the same token Number (tokenizedCardNumber) in my method as the data in the TOKEN_NUMBER column of my TFRAUDCARD table I still get a NullPointerException when I try to print a toString() of the Entity Object.
Here is the NullPointerException on my cloudFoundry logs (Click on it to see zoomed image) :
I'm providing the DB details in my dev properties file:
I have gone over every scenario in my head for why it breaks but I still can't come up with an answer. I'm using my variable marked with #Id i.e. the Primary Key for my find() method in the Repository.
I'm also adding a #Query annotation just to be even more specific.
It still does not work.

how can get the last inserted value in spring mongodb?

i have a class Named Device
#Document
public class Devise
{
#Id
public String id;
public String reference;
#DBRef
public List<Mesures> listMes;
public Devise() {
// TODO Auto-generated constructor stub
}
public Devise(String reference, List<Mesures> listMes) {
super();
this.reference = reference;
this.listMes = listMes;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getReference() {
return reference;
}
public void setReference(String reference) {
this.reference = reference;
}
public List<Mesures> getListMes() {
return listMes;
}
public void setListMes(List<Mesures> listMes) {
this.listMes = listMes;
}
}
another class named Mesures
#Document
public class Mesures {
#Id
private String id;
private Double value;
private Date date;
#DBRef
private Devise devise;
public Mesures() {
// TODO Auto-generated constructor stub
}
public Mesures(Double value, Date date, Devise devise) {
super();
this.value = value;
this.date = date;
this.devise = devise;
}
public Mesures(Double value, Date date) {
super();
this.value = value;
this.date = date;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Double getValue() {
return value;
}
public void setValue(Double value) {
this.value = value;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Devise getDevise() {
return devise;
}
public void setDevise(Devise devise) {
this.devise = devise;
}
and this is the MesuresRepository who extend from Mongo Repository
public interface MesureRepository extends MongoRepository<Mesures, String>{
public Mesures findTopByDeviseOrderByDateDesc(String DeviseId);
}
and this is the main app (Spring boot app)
ApplicationContext ctx = SpringApplication.run(UiApplication.class, args);
MesureDAO MDAO = ctx.getBean(MesureDAO.class);
DeviceDAO DDAO = ctx.getBean(DeviceDAO.class);
DateFormat df = new SimpleDateFormat("yyyy-mm-dd-hh-mm-ss");
Mesures m1 = new Mesures(10.0, df.parse("2016-11-12-12-51-42"));
Mesures m2 = new Mesures(15.2,df.parse("2016-11-12-12-52-42"));
//add Mesure
MDAO.addMesure(m1);
MDAO.addMesure(m2);
List<Mesures>listMes = new ArrayList<>();
listMes.add(m1);
listMes.add(m2);
//add Device
Devise D = new Devise("G2fgG123", listMes);
DDAO.addDevice(D);
and the database look like :
db.devise.find().pretty()
{
"_id" : ObjectId("58bc8218d980530898a0b047"),
"_class" : "demo.model.Devise",
"reference" : "G2fgG123",
"listMes" : [
DBRef("mesures", ObjectId("58bc8218d980530898a0b045")),
DBRef("mesures", ObjectId("58bc8218d980530898a0b046"))
]
}
and the restController like this
#RestController
public class MesuressController {
#Autowired
MesureRepository mesureRepo;
#RequestMapping(value = "/mesure/{DeviseId}")
public Mesures findByDeviseIdOrderByDate(#PathVariable("DeviseId")String DeviseId) {
return mesureRepo.findTopByDeviseIdOrderByDateDesc(DeviseId);
}}
and this is the measure Doc
db.mesures.find().pretty()
{
"_id" : ObjectId("58bc8218d980530898a0b045"),
"_class" : "demo.model.Mesures",
"value" : 10,
"date" : ISODate("2016-01-11T23:51:42Z")
}
{
"_id" : ObjectId("58bc8218d980530898a0b046"),
"_class" : "demo.model.Mesures",
"value" : 15.2,
"date" : ISODate("2016-01-11T23:52:42Z")
}
and this the device document after changing
db.devise.find().pretty()
{
"_id" : ObjectId("58bd306500ff6d1670916a7d"),
"_class" : "demo.model.Devise",
"reference" : "G2fgG123",
"listMes" : [
{
"_id" : ObjectId("58bd306500ff6d1670916a7b"),
"value" : 10,
"date" : ISODate("2016-01-11T23:51:42Z")
},
{
"_id" : ObjectId("58bd306500ff6d1670916a7c"),
"value" : 15.2,
"date" : ISODate("2016-01-11T23:52:42Z")
}
]
Try to use mongodb's $natural operator:
Query query = new Query().with(new Sort(Direction.ASC, "$natural"));
BasicQuery basicQuery = new BasicQuery(new BasicDBObject());
basicQuery.setSortObject(new BasicDBObject("$natural", -1));

Getting Null Pointer Exception Mongo Aggregation Using Spring Data(Dynamic Fields)

This is my Mongo Pojo also getters and setters(Not added) .
#CompoundIndex(name = "account_date_idx", def = "{'account' : 1, 'date' : 1}", unique = true)
#Document(collection = "agent_data_storage")
public class AgentDataStorage extends MongoKeyedEntity<String> implements Serializable {
public static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
#Field
private Long account;
#Field()
private String date;
#Field
private Map<String, Double> dataPoints = new HashMap<>();
public AgentDataStorage() {
}
public AgentDataStorage(Long account) {
this.account = account;
this.date = dateFormat.format(new Date());
for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
this.dataPoints.put(dataPoint.toString(), 0d);
}
}
public AgentDataStorage(String account) {
this.account = Long.valueOf(account);
for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
this.dataPoints.put(dataPoint.toString(), 0d);
}
}
public AgentDataStorage(Long account, Date date) {
this.account = account;
this.date = dateFormat.format(date);
for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
this.dataPoints.put(dataPoint.toString(), 0d);
}
}
public AgentDataStorage(Long account, Date date, Map<String, Double> dataPoints) {
this.account = account;
this.date = dateFormat.format(date);
this.dataPoints = dataPoints;
}
public AgentDataStorage(Long account, String date, Map<String, Double> dataPoints) {
this.account = account;
this.date = date;
this.dataPoints = dataPoints;
}
public AgentDataStorage(String account, Date date) {
this.account = Long.valueOf(account);
this.date = dateFormat.format(date);
for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
this.dataPoints.put(dataPoint.toString(), 0d);
}
}
public AgentDataStorage(String account, String date) {
this.account = Long.valueOf(account);
this.date = date;
for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
this.dataPoints.put(dataPoint.toString(), 0d);
}
}
public Long getAccount() {
return account;
}
public void setAccount(Long account) {
this.account = account;
}
public Date getDate() throws ParseException {
return dateFormat.parse(this.date);
}
public void setDate(Date date) {
this.date = dateFormat.format(date);
}
public Map<String, Double> getDataPoints() {
return dataPoints;
}
public void setDataPoints(Map<String, Double> dataPoints) {
this.dataPoints = dataPoints;
}
public void updateDataPoint(AgentDataPoints agentDataPoints, Double value) {
this.dataPoints.put(String.valueOf(agentDataPoints), value);
}
#Override
public String toString() {
final StringBuilder sb = new StringBuilder("AgentDataStorage{");
sb.append("account=").append(account);
sb.append(", date=").append(date);
sb.append(", dataPoints=").append(dataPoints);
sb.append('}');
return sb.toString();
}
}
While Trying aggregation i am getting null Pointer Exception , Below is my Test Case.
#Test
public void aggregationTest() {
Long account = 12121l;
String startDay = "2016-01-01";
String endDay = "2016-01-03";
Aggregation aggregation = Aggregation
.newAggregation(match(Criteria.where("account").is(account).and("date")
.gte(startDay).lte(endDay)),
group("account").sum("dataPoints.TOTAL_BUS_COMMISSION").as("total"));
AggregationResults<AggregationResult> results = mongoTemplate.aggregate(aggregation,
AgentDataStorage.class, AggregationResult.class);
}
My AggregationResult class is -
public class AggregationResult {
private Long _id;
private Double total;
public Long get_id() {
return _id;
}
public void set_id(Long _id) {
this._id = _id;
}
public Double getTotal() {
return total;
}
public void setTotal(Double total) {
this.total = total;
}
}
Below is Stack Trace Of Error
java.lang.NullPointerException
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentPropertyPath(AbstractMappingContext.java:233)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentPropertyPath(AbstractMappingContext.java:214)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentPropertyPath(AbstractMappingContext.java:210)
at org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext.getReferenceFor(TypeBasedAggregationOperationContext.java:96)
at org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext.getReference(TypeBasedAggregationOperationContext.java:91)
at org.springframework.data.mongodb.core.aggregation.GroupOperation$Operation.getValue(GroupOperation.java:434)
at org.springframework.data.mongodb.core.aggregation.GroupOperation$Operation.toDBObject(GroupOperation.java:416)
at org.springframework.data.mongodb.core.aggregation.GroupOperation.toDBObject(GroupOperation.java:361)
at org.springframework.data.mongodb.core.aggregation.Aggregation.toDbObject(Aggregation.java:331)
at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1500)
at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1435)
at psl.service.core.agentanalytics.internal.AgentAnalyticsServiceTest.aggregationTest(AgentAnalyticsServiceTest.java:132)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:72)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:81)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:216)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:82)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:60)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:67)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:162)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
I also tried to debug the inside spring jar , It's throwing null for Double type inside AbstractMappingContext.java but not able to understant why it's happening .
The same mongo query is working in mongo console.
db.getCollection('agent_data_storage').aggregate([
{ "$match" : { "account" : 12121 , "date" : { "$gte" : "2016-01-01" , "$lte" : "2016-01-03"}}}
, { "$group" : { "_id" : "$account" , "total" : { "$sum" : "$dataPoints.TOTAL_BUS_COMMISSION"}}}])
the result for the above query is
{
"_id" : NumberLong(12121),
"total" : 402.0
}
Thanks for any kind of Help .
Sample Doc from AgentDataStorage-
{
"_id" : ObjectId("586233e3fb94f6f5640196cf"),
"account" : NumberLong(12121),
"date" : "2016-01-01",
"dataPoints" : {
"TOTAL_BUS_COMMISSION" : 0.0
}
}
Don't use the typed aggregation variant of aggregation which is essentially trying to translate property references in the input type (AgentDataStorage) into field names and fails when it doesn't find the property references, in your case dataPoints.TOTAL_BUS_COMMISSION.
Use
AggregationResults<AggregationResult> results = mongoTemplate.aggregate(aggregation,
"agent_data_storage", AggregationResult.class);

spring data neo4j ,i can't solve it

I use spring data neo4j,i have user.class.movie.class,rating.class,i create relationship between movie and rating,when i run the programer,i can get the rating(star,comment)but cannot get the movie's title(null)
movie.class
package com.oberon.fm.domain;
#NodeEntity
public class Movie {
#GraphId
Long nodeId;
#Indexed(indexType = IndexType.FULLTEXT, indexName = "id")
String id;
#Indexed(indexType = IndexType.FULLTEXT, indexName = "search", numeric = false)
String title;
String description;
#RelatedTo(type = "DIRECTED", direction = INCOMING)
Person director;
#RelatedTo(type = "ACTS_IN", direction = INCOMING)
Set<Person> actors;
#RelatedToVia(elementClass = Role.class, type = "ACTS_IN", direction = INCOMING)
// Iterable<Role> roles;
Set<Role> roles = new HashSet<>();
#RelatedToVia(elementClass = Rating.class, type = "RATED", direction = INCOMING)
#Fetch
Iterable<Rating> ratings;
// Set<Rating> ratings = new HashSet<>();
private String language;
private String imdbId;
private String tagline;
private Date releaseDate;
private Integer runtime;
private String homepage;
private String trailer;
private String genre;
private String studio;
private Integer version;
private Date lastModified;
private String imageUrl;
public Movie() {
}
public Long getNodeId() {
return nodeId;
}
public void setNodeId(Long nodeId) {
this.nodeId = nodeId;
}
public Movie(String id, String title) {
this.id = id;
this.title = title;
}
public Collection<Person> getActors() {
return actors;
}
public Collection<Role> getRoles() {
return IteratorUtil.asCollection(roles);
}
public int getYear() {
if (releaseDate == null)
return 0;
Calendar cal = Calendar.getInstance();
cal.setTime(releaseDate);
return cal.get(Calendar.YEAR);
}
public String getId() {
return id;
}
public String getTitle() {
return title;
}
#Override
public String toString() {
return String.format("%s (%s) [%s]", title, releaseDate, id);
}
public String getDescription() {
return description;
}
public int getStars() {
Iterable<Rating> allRatings = ratings;
if (allRatings == null)
return 0;
int stars = 0, count = 0;
for (Rating rating : allRatings) {
stars += rating.getStars();
count++;
}
return count == 0 ? 0 : stars / count;
}
public Collection<Rating> getRatings() {
Iterable<Rating> allRatings = ratings;
return allRatings == null ? Collections.<Rating> emptyList()
: IteratorUtil.asCollection(allRatings);
}
/*
* public Set<Rating> getRatings() { return ratings; }
*/
public void setRatings(Set<Rating> ratings) {
this.ratings = ratings;
}
/*
* public void addRating(Rating rating) { ratings.add(rating); }
*/
public void setTitle(String title) {
this.title = title;
}
public void setLanguage(String language) {
this.language = language;
}
public void setImdbId(String imdbId) {
this.imdbId = imdbId;
}
public void setTagline(String tagline) {
this.tagline = tagline;
}
public void setDescription(String description) {
this.description = description;
}
public void setReleaseDate(Date releaseDate) {
this.releaseDate = releaseDate;
}
public void setRuntime(Integer runtime) {
this.runtime = runtime;
}
public void setHomepage(String homepage) {
this.homepage = homepage;
}
public void setTrailer(String trailer) {
this.trailer = trailer;
}
public void setGenre(String genre) {
this.genre = genre;
}
public void setStudio(String studio) {
this.studio = studio;
}
public void setVersion(Integer version) {
this.version = version;
}
public void setLastModified(Date lastModified) {
this.lastModified = lastModified;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getLanguage() {
return language;
}
public String getImdbId() {
return imdbId;
}
public String getTagline() {
return tagline;
}
public Date getReleaseDate() {
return releaseDate;
}
public Integer getRuntime() {
return runtime;
}
public String getHomepage() {
return homepage;
}
public String getTrailer() {
return trailer;
}
public String getGenre() {
return genre;
}
public String getStudio() {
return studio;
}
public Integer getVersion() {
return version;
}
public Date getLastModified() {
return lastModified;
}
public String getImageUrl() {
return imageUrl;
}
public String getYoutubeId() {
String trailerUrl = trailer;
if (trailerUrl == null || !trailerUrl.contains("youtu"))
return null;
String[] parts = trailerUrl.split("[=/]");
int numberOfParts = parts.length;
return numberOfParts > 0 ? parts[numberOfParts - 1] : null;
}
#Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Movie movie = (Movie) o;
if (nodeId == null)
return super.equals(o);
return nodeId.equals(movie.nodeId);
}
#Override
public int hashCode() {
return nodeId != null ? nodeId.hashCode() : super.hashCode();
}
public Person getDirector() {
return director;
}
}
user.class
package com.oberon.fm.domain;
#NodeEntity
public class User {
#GraphId
Long nodeId;
public static final String SALT = "cewuiqwzie";
public static final String FRIEND = "FRIEND";
public static final String RATED = "RATED";
#Indexed(indexType = IndexType.FULLTEXT, indexName = "login")
String login;
#Indexed
String name;
String password;
public void setPassword(String password) {
this.password = password;
}
String info;
private Roles[] roles;
public User() {
}
public User(String login, String name, String password, Roles... roles) {
this.login = login;
this.name = name;
this.password = encode(password);
this.roles = roles;
}
private String encode(String password) {
return new Md5PasswordEncoder().encodePassword(password, SALT);
}
#RelatedToVia(type = RATED)
#Fetch
Iterable<Rating> ratings;
// Set<Rating> ratings = new HashSet<>();
#RelatedTo(type = RATED)
Set<Movie> favorites;
public Set<Movie> getFavorites() {
return favorites;
}
public void setFavorites(Set<Movie> favorites) {
this.favorites = favorites;
}
#RelatedTo(type = FRIEND, direction = Direction.BOTH)
#Fetch
Set<User> friends;
public void addFriend(User friend) {
this.friends.add(friend);
}
public Rating rate(Neo4jOperations template, Movie movie, int stars,
String comment) {
final Rating rating = template.createRelationshipBetween(this, movie,
Rating.class, RATED, false).rate(stars, comment);
return template.save(rating);
}
/*
* public Rating rate(Movie movie, int stars, String comment) { if (ratings
* == null) { ratings = new HashSet<>(); }
*
* Rating rating = new Rating(this, movie, stars, comment);
* ratings.add(rating); movie.addRating(rating); return rating; }
*/
public Collection<Rating> getRatings() {
return IteratorUtil.asCollection(ratings);
}
/*
* public Set<Rating> getRatings() { return ratings; }
*/
#Override
public String toString() {
return String.format("%s (%s)", name, login);
}
public String getName() {
return name;
}
public Set<User> getFriends() {
return friends;
}
public Roles[] getRole() {
return roles;
}
public String getLogin() {
return login;
}
public String getPassword() {
return password;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public void updatePassword(String old, String newPass1, String newPass2) {
if (!password.equals(encode(old)))
throw new IllegalArgumentException("Existing Password invalid");
if (!newPass1.equals(newPass2))
throw new IllegalArgumentException("New Passwords don't match");
this.password = encode(newPass1);
}
public void setName(String name) {
this.name = name;
}
public boolean isFriend(User other) {
return other != null && getFriends().contains(other);
}
public enum Roles implements GrantedAuthority {
ROLE_USER, ROLE_ADMIN;
#Override
public String getAuthority() {
return name();
}
}
#Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
User user = (User) o;
if (nodeId == null)
return super.equals(o);
return nodeId.equals(user.nodeId);
}
public Long getId() {
return nodeId;
}
#Override
public int hashCode() {
return nodeId != null ? nodeId.hashCode() : super.hashCode();
}
}
rating.class
package com.oberon.fm.domain;
#RelationshipEntity
public class Rating {
private static final int MAX_STARS = 5;
private static final int MIN_STARS = 0;
#GraphId
Long id;
#StartNode
User user;
#EndNode
Movie movie;
int stars;
String comment;
public User getUser() {
return user;
}
public Movie getMovie() {
return movie;
}
public int getStars() {
return stars;
}
public void setStars(int stars) {
this.stars = stars;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public Rating rate(int stars, String comment) {
if (stars >= MIN_STARS && stars <= MAX_STARS)
this.stars = stars;
if (comment != null && !comment.isEmpty())
this.comment = comment;
return this;
}
public Rating() {
}
public void setUser(User user) {
this.user = user;
}
public void setMovie(Movie movie) {
this.movie = movie;
}
#Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Rating rating = (Rating) o;
if (id == null)
return super.equals(o);
return id.equals(rating.id);
}
#Override
public int hashCode() {
return id != null ? id.hashCode() : super.hashCode();
}
}
controller
#RequestMapping(value = "/user", method = RequestMethod.GET)
public String profile(Model model, HttpServletRequest request) {
// User user=populator.getUserFromSession();
HttpSession session = request.getSession(false);
User user = (User) session.getAttribute("user");
model.addAttribute("user", user);
if (user != null) {
List<MovieRecommendation> mr = movieRepository.getRecommendations(user.getLogin());
MovieRecommendation movie = new MovieRecommendation();
Movie m = new Movie();
m.setTitle("AA");
movie.setMovie(m);
mr.add(movie);
model.addAttribute("recommendations", mr);
}
return "user/index";
}![enter image description here][4]
It only loads the movie's id by default, if you don't specify #Fetch on the movie field. But I'd rather recommend to use template.fetch(rating.movie) to load it only when you need it.

Resources