how can get the last inserted value in spring mongodb? - spring

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));

Related

org.hibernate.exception.DataException: could not execute query in spring boot and Data JPA

When I am trying to implement the JPQL query, I am getting the following error,
{
"message": "could not execute query; SQL [select alerts0_.nalert_id as nalert_i1_0_, alerts0_.bis_active as bis_acti2_0_, alerts0_.dalert_date as dalert_d3_0_, alerts0_.ndept_to as ndept_to4_0_, alerts0_.ninst_to as ninst_to5_0_, alerts0_.nreceiver_id as nreceive6_0_, alerts0_.nsender_id as nsender_7_0_, alerts0_.nsubdept_to as nsubdept8_0_, alerts0_.salert_action_data as salert_a9_0_, alerts0_.salert_desc as salert_10_0_, alerts0_.salert_subject as salert_11_0_, alerts0_.salert_type as salert_12_0_ from alerts alerts0_ where alerts0_.ninst_to=?]; nested exception is org.hibernate.exception.DataException: could not execute query",
"error": "Internal Server Error",
"path": "/spacestudy/rockefeller/control/alerts/getAlertDetails"
}
And my repository query is like the following,
#Query("SELECT a FROM Alerts a")
public List<Alerts> findByAlertType();
When I hard-coded Query like #Query("SELECT a FROM Alerts a WHERE a.nreceiverId = 649"), then also getting the same error.
And I am calling this query in my service like the following:
alert= alertsRepositoryObj.findByAlertType();
And my model class Alerts.java like the following:
#Entity
#Table(name="alerts")
public class Alerts implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "alerts_seq_generator")
#SequenceGenerator(name = "alerts_seq_generator", sequenceName = "alerts_seq",allocationSize=1)
#Column(name="nalert_id",columnDefinition="serial")
public Integer nalertId;
#Column(name="salert_desc")
public String salertDesc;
#NotNull
#Column(name="nsender_id")
public Integer nsenderId;
#Column(name="dalert_date")
public LocalDate dalertDate;
#Column(name="salert_subject")
public String salertSubject;
#Column(name="salert_action_data")
public String salertActionData;
#Column(name="salert_type")
public String salertType;
#Column(name="ninst_to")
public Integer ninstTo;
#Column(name="ndept_to")
public Integer nDeptTo;
#Column(name="nsubdept_to")
public Integer nsubdeptTo;
#Column(name="nreceiver_id")
public Integer nreceiverId;
#NotNull
#Column(name="bis_active")
public Boolean bisActive=true;
#ManyToOne(optional = true)
#JoinColumn(name = "salert_action_data", insertable = false, updatable = false)
public RoomTransfer roomTransfer;
public Integer getNalertId()
{
return nalertId;
}
public void setNalertId(Integer nalertId)
{
this.nalertId = nalertId;
}
public String getSalertDesc()
{
return salertDesc;
}
public void setSalertDesc(String salertDesc)
{
this.salertDesc = salertDesc;
}
public Integer getNsenderId()
{
return nsenderId;
}
public void setNsenderId(Integer nsenderId)
{
this.nsenderId = nsenderId;
}
public LocalDate getDalertDate()
{
return dalertDate;
}
public void setDalertDate(LocalDate dalertDate)
{
this.dalertDate = dalertDate;
}
public String getSalertSubject()
{
return salertSubject;
}
public void setSalertSubject(String salertSubject)
{
this.salertSubject = salertSubject;
}
public String getSalertActionData()
{
return salertActionData;
}
public void setSalertActionData(String salertActionData)
{
this.salertActionData = salertActionData;
}
public String getSalertType()
{
return salertType;
}
public void setSalertType(String salertType)
{
this.salertType = salertType;
}
public Integer getNinstTo()
{
return ninstTo;
}
public void setNinstTo(Integer ninstTo)
{
this.ninstTo = ninstTo;
}
public Integer getnDeptTo()
{
return nDeptTo;
}
public void setnDeptTo(Integer nDeptTo)
{
this.nDeptTo = nDeptTo;
}
public Integer getNsubdeptTo()
{
return nsubdeptTo;
}
public void setNsubdeptTo(Integer nsubdeptTo)
{
this.nsubdeptTo = nsubdeptTo;
}
public Integer getNreceiverId()
{
return nreceiverId;
}
public void setNreceiverId(Integer nreceiverId)
{
this.nreceiverId = nreceiverId;
}
public Boolean getBisActive()
{
return bisActive;
}
public void setBisActive(Boolean bisActive)
{
this.bisActive = bisActive;
}
public RoomTransfer getRoomTransfer()
{
return roomTransfer;
}
public void setRoomTransfer(RoomTransfer roomTransfer)
{
this.roomTransfer = roomTransfer;
}
public Alerts()
{
super();
}
}
Why this error happening? Since this is a simple JPQL query. How can I trouble shoot the exact error here?

Graphql - Query returns null

I am using the graphql-java-annotations library for java to retrieve data from my spring backend.
<dependency>
<groupId>io.github.graphql-java</groupId>
<artifactId>graphql-java-annotations</artifactId>
<version>7.1</version>
</dependency>
When I call the query it always return null.
This is my Provider class:
GraphQLAnnotations graphqlAnnotations = new GraphQLAnnotations();
GraphQLSchema graphQLSchema = newSchema()
.query(graphqlAnnotations.object(QueryTest.class))
.build();
this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();
This is the query:
#GraphQLName("queryTest")
public class QueryTest {
#GraphQLField
public static Test byId(final DataFetchingEnvironment env, #GraphQLName("id") Long id) {
return new Test();
}
}
And finally the Test.class
#GraphQLName("Test")
public class Test {
private String id;
private String name;
public Test() {
this("0");
}
public Test(String id) {
this.setName("Name" + id);
this.setId(id);
}
#GraphQLField
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#GraphQLField
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
This is my call:
{
"query" : "query queryTest { byId(id: 2) { getId } }",
"operationName" : "queryTest"
}
And this is the result i get:
{
"data": {
"byId": null
}
}
I debugged into the graphql execution and found out that schema contains TestClass and Test. So type and query are known. With this configuration I don't have a fetcher or a resolver.
Found the solution:
I had to change my Provider class in order to create the schema correctly via the AnnotationsSchemaCreator Builder:
GraphQLSchema graphQLSchema = AnnotationsSchemaCreator.newAnnotationsSchema()
.query(QueryTest.class)
.typeFunction(new ZonedDateTimeFunction())
.build();
this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();

hibernate/Spring/Jpa #oneToMany cascade update

I'm trying to add in the decorator cascade = CascadeType.ALL on the field one to many of my version modele in spring in order to update every hyper parameter when i update my version.Like you can see below.
#Entity
#Table(name = "version")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Version implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Column(name = "num", nullable = false)
private Integer num;
#Column(name = "creation_date")
private ZonedDateTime creationDate;
#Column(name = "execution_date")
private ZonedDateTime executionDate;
#Column(name = "weights_uri")
private String weightsURI;
#OneToMany(mappedBy = "version", fetch = FetchType.EAGER, orphanRemoval = true)
#JsonIgnoreProperties({"version", "metricsType"})
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<ResultExecution> resultExecutions = new HashSet<>();
#OneToMany(mappedBy = "version", fetch = FetchType.EAGER, orphanRemoval = true, cascade = CascadeType.ALL)
#JsonIgnoreProperties({"version"})
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<HyperParameter> hyperParameters = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getNum() {
return num;
}
public Version num(Integer num) {
this.num = num;
return this;
}
public void setNum(Integer num) {
this.num = num;
}
public ZonedDateTime getCreationDate() {
return creationDate;
}
public Version creationDate(ZonedDateTime creationDate) {
this.creationDate = creationDate;
return this;
}
public void setCreationDate(ZonedDateTime creationDate) {
this.creationDate = creationDate;
}
public ZonedDateTime getExecutionDate() {
return executionDate;
}
public Version executionDate(ZonedDateTime executionDate) {
this.executionDate = executionDate;
return this;
}
public void setExecutionDate(ZonedDateTime executionDate) {
this.executionDate = executionDate;
}
public String getWeightsURI() {
return weightsURI;
}
public Version weightsURI(String weightsURI) {
this.weightsURI = weightsURI;
return this;
}
public void setWeightsURI(String weightsURI) {
this.weightsURI = weightsURI;
}
public Set<ResultExecution> getResultExecutions() {
return resultExecutions;
}
public Version resultExecutions(Set<ResultExecution> resultExecutions) {
this.resultExecutions = resultExecutions;
return this;
}
public Version addResultExecution(ResultExecution resultExecution) {
this.resultExecutions.add(resultExecution);
resultExecution.setVersion(this);
return this;
}
public Version removeResultExecution(ResultExecution resultExecution) {
this.resultExecutions.remove(resultExecution);
resultExecution.setVersion(null);
return this;
}
public void setResultExecutions(Set<ResultExecution> resultExecutions) {
this.resultExecutions = resultExecutions;
}
public Set<HyperParameter> getHyperParameters() {
return hyperParameters;
}
public Version hyperParameters(Set<HyperParameter> hyperParameters) {
this.hyperParameters = hyperParameters;
return this;
}
public Version addHyperParameter(HyperParameter hyperParameter) {
this.hyperParameters.add(hyperParameter);
hyperParameter.setVersion(this);
return this;
}
public Version removeHyperParameter(HyperParameter hyperParameter) {
this.hyperParameters.remove(hyperParameter);
hyperParameter.setVersion(null);
return this;
}
public void setHyperParameters(Set<HyperParameter> hyperParameters) {
this.hyperParameters = hyperParameters;
}
public Set<Data> getData() {
return data;
}
public Version data(Set<Data> data) {
this.data = data;
return this;
}
public Version addData(Data data) {
this.data.add(data);
data.getVersions().add(this);
return this;
}
public Version removeData(Data data) {
this.data.remove(data);
data.getVersions().remove(this);
return this;
}
public void setData(Set<Data> data) {
this.data = data;
}
public ModelConfiguration getModelConfiguration() {
return modelConfiguration;
}
public Version modelConfiguration(ModelConfiguration modelConfiguration) {
this.modelConfiguration = modelConfiguration;
return this;
}
public void setModelConfiguration(ModelConfiguration modelConfiguration) {
this.modelConfiguration = modelConfiguration;
}
// jhipster-needle-entity-add-getters-setters - Jhipster will add getters and setters here, do not remove
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Version version = (Version) o;
if (version.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), version.getId());
}
#Override
public int hashCode() {
return Objects.hashCode(getId());
}
#Override
public String toString() {
return "Version{" +
"id=" + getId() +
", num='" + getNum() + "'" +
", creationDate='" + getCreationDate() + "'" +
", executionDate='" + getExecutionDate() + "'" +
", weightsURI='" + getWeightsURI() + "'" +
"}";
}
}
My hyperParameter model looks like this :
#Entity
#Table(name = "hyper_parameter")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class HyperParameter implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Column(name = "parameter_value", nullable = false)
private String parameterValue;
#ManyToOne(optional = false)
#NotNull
#JsonIgnoreProperties({"resultExecutions", "hyperParameters", "data", "modelConfiguration"})
private Version version;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getParameterValue() {
return parameterValue;
}
public HyperParameter parameterValue(String parameterValue) {
this.parameterValue = parameterValue;
return this;
}
public void setParameterValue(String parameterValue) {
this.parameterValue = parameterValue;
}
public Version getVersion() {
return version;
}
public HyperParameter version(Version version) {
this.version = version;
return this;
}
public void setVersion(Version version) {
this.version = version;
}
public HyperParameterType getHyperParameterType() {
return hyperParameterType;
}
public HyperParameter hyperParameterType(HyperParameterType hyperParameterType) {
this.hyperParameterType = hyperParameterType;
return this;
}
public void setHyperParameterType(HyperParameterType hyperParameterType) {
this.hyperParameterType = hyperParameterType;
}
// jhipster-needle-entity-add-getters-setters - Jhipster will add getters and setters here, do not remove
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
HyperParameter hyperParameter = (HyperParameter) o;
if (hyperParameter.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), hyperParameter.getId());
}
#Override
public int hashCode() {
return Objects.hashCode(getId());
}
#Override
public String toString() {
return "HyperParameter{" +
"id=" + getId() +
", parameterValue='" + getParameterValue() + "'" +
"}";
}
}
I update a json and try a put with it .I change the value of the field parametervalue from 2 to 3 .
{
"id": 1,
"num": 1,
"creationDate": "2017-05-11T00:00:00+02:00",
"executionDate": null,
"weightsURI": "tests/scripts/sequential/weights/weights_le_net_5.h5py",
"resultExecutions": [
{
"id": 1,
"metricValues": "",
"executionType": "TRAIN",
"numPrediction": null
},
{
"id": 2,
"metricValues": "",
"executionType": "TRAIN",
"numPrediction": null
}
],
"hyperParameters": [
{
"id": 1,
"parameterValue": "2",
"hyperParameterType": {
"id": 1,
"name": "epochs",
"parameterType": "INTEGER",
"parameterDefaultValue": "0",
"isRequired": true
}
},
{
"id": 2,
"parameterValue": "32",
"hyperParameterType": {
"id": 2,
"name": "batch_size",
"parameterType": "INTEGER",
"parameterDefaultValue": "32",
"isRequired": true
}
}
],
"modelConfiguration": {
"id": 1,
"name": "Modele LeNet5",
"creationDate": "2017-05-11T00:00:00+02:00",
"updateDate": "2017-05-11T00:00:00+02:00",
"saveURI": "tests/scripts/sequential/models/le_net_5.json"
}
}
But when i do i got a 500 internal serveur error and stack trace like the one bellow about a null constraint violation.
<!-- What do you expect the result to be? -->
<!-- What is the actual result you get? (Please include any errors.) -->
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:526)
[1:59]
t org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:75)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:71)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
... 153 common frames omitted
Caused by: javax.validation.ConstraintViolationException: Validation failed for classes [com.saagie.picsaagie2017_frontend.domain.HyperParameter] during update time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='can not be null ', propertyPath=version, rootBeanClass=class com.saagie.picsaagie2017_frontend.domain.HyperParameter, messageTemplate='{javax.validation.constraints.NotNull.message}'}
]
How can i update my hyperParameters when i update my version whitout getting this error.
Use the #PreUpdate and #PrePersist callbacks in the HyperParameter class like so:
#PreUpdate
#PrePersist
public void setChildObjects() {
if (getVersions() != null)
{
for (Version version : getVersions())
{
version.setHyperParameters (this);
}
}
}
Refer to this for more information : http://docs.jboss.org/hibernate/core/3.3/reference/en/html/tutorial.html#tutorial-associations-usingbidir
Both solution actually work i had a second error because of what is discussed in that topic : Spring data rest one to many cascade all . I just had to add #JsonManagedReference and #JsonBackReference because i had marshalling problem on the reference of version when i tried to update my HyperParameters in cascade.
You just have validation error. You try to put interpolatedMessage with null value. Ok but first remove #NotNull annotation on this field.

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);

mongoTemplate: custom converter with non standard objects

I found an issue when using a custom converter.
Let's say my to objects are:
public class Foo {
private String id;
private Bar bar;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Bar getBar() {
return bar;
}
public void setBar(Bar bar) {
this.bar = bar;
}
}
public class Bar {
private String id;
private String property;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
}
If they are inserted into the MongoDB, everything works fine, as long as no custom converter is involved.
Bar bar = new Bar();
bar.setProperty("Test");
Foo foo = new Foo();
foo.setBar(bar);
mongoTemplate.insert(bar);
mongoTemplate.insert(foo);
Results:
{
"_id" : {
"$oid" : "51a346059f2c9d656019798e"
},
"_class" : "Bar",
"property" : "Test"
}
{
"_id" : {
"$oid" : "51a346059f2c9d656019798f"
},
"_class" : "Foo",
"bar" : {
"_id" : {
"$oid" : "51a346059f2c9d656019798e"
},
"property" : "Test"
}
}
Now I wrote a custom converter, cause Foo needs to be stored in a special way.
public class FooWriteConverter implements Converter<Foo, DBObject> {
#Override
public DBObject convert(Foo source) {
DBObject dbo = new BasicDBObject();
dbo.put("id", source.getId());
dbo.put("bar", source.getBar());
return dbo;
}
}
Now I get this error.
Caused by: java.lang.IllegalArgumentException: can't serialize class Bar
So, it looks like I can't fall back to the default conversion for properties of an object, that is converted using a custom converter?!
Any useful solutions instead of doing all conversion manually?
In order to use default conversion for properties in custom converter you need a MongoConverter class help.
public class FooWriteConverter implements Converter<Foo, DBObject> {
private MongoConverter mongoConverter;
public FooWriteConverter(MongoConverter mongoConverter) {
this.mongoConverter = mongoConverter;
}
#Override
public DBObject convert(Foo source) {
DBObject dbo = new BasicDBObject();
dbo.put("id", source.getId());
DBObject bar = new BasicDBObject();
mongoConverter.write(source.getBar(), bar);
dbo.put("bar", bar);
return dbo;
}
}

Resources