NullPointerException while using MongoTemplate in Spring boot - mongodb

I have a collection named 'statusbynumbers' and I define the entity like this:
#Document(collection="statusbynumbers")
#Data
#AllArgsConstructor
#NoArgsConstructor
public class StatusByNumbersEntity {
#Id
private String id;
#Field("number")
private String number;
#Field("level")
private String
#Field("yat")
private double yat;
}
the key 'yat' is a double type in the db. But in my business logic, in some cases, 'yat' can be null. Then when I uses MongoTemplate.find() method, java.lang.NullPointerException: null was caused. The MongoTemplate.find() used in my code shown as below:
public class ReportsServiceImpl implements ReportsService {
#Resource
private MongoTemplate ReportsMongoTemplate;
#Override
public List<StatusByNumbersEntity> getNumbersByFilterLevel(String filterLevel) {
List<Integer> filterLevelList = FilterLevelModel.buildFilterLevel(filterLevel);
Criteria criteria = Criteria.where("level").in(filterLevelList);
Query query = new Query(criteria);
// java.lang.NullPointerException: null caused by the following code
List<StatusByNumbersEntity> numList = ReportsMongoTemplate.find(query,StatusByNumbersEntity.class);
...
}
The detailed error log shown as below
2017-10-10 02:47:06.475 ERROR org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is
java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
at sun.invoke.util.ValueConversions.unboxDouble(ValueConversions.java:139)
at com.test.application.entities.reports.numbersEntity_Accessor_22t0xt.setProperty(Unknown Source)
at org.springframework.data.mapping.model.ConvertingPropertyAccessor.setProperty(ConvertingPropertyAccessor.java:58)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$1.doWithPersistentProperty(MappingMongoConverter.java:291)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$1.doWithPersistentProperty(MappingMongoConverter.java:279)
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:330)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:279)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:239)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:199)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:195)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:85)
at org.springframework.data.mongodb.core.MongoTemplate$ReadDbObjectCallback.doWith(MongoTemplate.java:2324)
at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:1969)
at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1787)
at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1770)
at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:644)
at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:635)
How can i use the MongoTemplate.find() method even if the key "yat" can be null instead of double type to avoid this NullPointerException?

It's because you used a primitive type variable(double with lowercase 'd') for a nullable field.
You can't set null value for primitive data types(trows NullPointerException)
Replace 'double' with 'Double'
#Field("yat")
private Double yat;
Remember that you can't cast a null value to primitive data types either.
for when you had setters and getters replace the primitive type with non-primitive equivalent in them as well.
more details:
https://www.w3schools.com/java/java_data_types.asp

Related

JPA Repository findByEnum does not cast the Argument Enum to String or Postgres Cast not working as expected

I have a Spring Boot (2.5.4) backend pointing to a Postgres (9.6) database. I have an entity in Spring that makes use of the #Enumerated(EnumType.String) annotation on a field of an Enum type. Persisting this entity works as expected and converts the Enum into a String. In Postgres, I have the respective enum casted to character varying. Things are working to this point except invoking a custom findBy "Enum" method in the JPA Repository interface. Now in Spring and Postgres I have defined the following:
Enum:
public enum EnumExampleType {
TYPE1, TYPE2
}
Entity:
#Entity
#Table(name = "enumexampletable")
#Data
#NoArgsConstructor
public class EnumExampleTable {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "enum_example_table_id", columnDefinition="serial primary key")
private int enumExampleTableId;
#Column(unique = true, name="enum_example_type")
#Enumerated(EnumType.STRING)
public EnumExampleType enumExampleType;
}
Repo:
public interface EnumExampleTableRepo extends JpaRepository<EnumExampleTable, Integer> {
EnumExampleTable findByEnumExampleType(EnumExampleType enumExampleType);
}
Working Code as Expected
EnumExampleTable ex1 = new EnumExampleTable();
EnumExampleTable ex2 = new EnumExampleTable();
ex1.setEnumExampleType(EnumExampleType.TYPE1);
ex2.setEnumExampleType(EnumExampleType.TYPE2);
enumExampleTableRepo.save(ex1);
enumExampleTableRepo.save(ex2);
RestController: (to invoke) (not working)
#Autowired
EnumExampleTableRepo enumExampleTableRepo;
#GetMapping("/findByTest")
public EnumExampleTable enumTest() {
return enumExampleTableRepo.findByEnumExampleType(EnumExampleType.TYPE1);
}
When calling this code the following error is received:
Blockquote org.postgresql.util.PSQLException: ERROR: operator does not exist: enumexampletype = character varying
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Postgres Database:
drop table if exists enumexampletable;
drop type if exists enumexampletype cascade;
drop cast if exists (character varying as enumexampletype);
create type enumexampletype as enum('TYPE1', 'TYPE2');
CREATE CAST (character varying as enumexampletype) with inout as implicit;
create table enumexampletable (
enum_example_table_id serial primary key,
enum_example_type enumexampletype
);
This suggests to me that either:
A: The findByEnumExampleType method does not convert the enum to a string
B: Postgres does not invoke this cast in this particular call
Also to Note: (A hard coded native query will function properly, but this is not the dynamic functionality I need)
#Query(value="select * from enumexampletable e where e.emum_example_type = 'TYPE1'", nativeQuery=true)
EnumExampleTable testNQ();
Thoughts or suggestions?

Drools get object from map mvel cast exception

I am using jboss EAP 7.2 and Red Hat Decision Central 7.5.0
I have a custom objects like that
public class Model{
private String id;
private Map<String, Object> map;
// ... getters and setters
}
public class ParameterModel{
private String parameterName;
private BigDecimal maxValue;
private BigDecimal minValue;
private Object value;
// ... getters and setters
}
I have created new "Model" object that has custom "id" attribute and "map" attribute contains <parameterName, ParameterModel> pairs.
I sent it to decision manager and drools side ı want to achieve ParameterModel attributes but I could not.
My rule is below.
package com.rule.test;
import com.test.Model;
import com.test.ParameterModel;
rule "drools1"
when
Model(getId().equals("1"), Integer.parseInt(((ParameterModel)getMap().get("param1")).getValue().toString())>10)
then
System.out.println("Error on " + drools.getRule().getName());
end
The exception is below.
Caused by: [Error: null pointer:
Integer.parseInt(((ParameterModel)getMap().get("param1")).getValue().toString())]
[Near : {... Integer.parseInt(((ParameterMo ....}] In [Rule "drools1"
in com/rule/test/test.drl]
Caused by: java.lang.NullPointerException
at org.mvel2.DataConversion.convert(DataConversion.java:129)
at org.mvel2.ast.TypeCast.getReducedValueAccelerated(TypeCast.java:74)
at org.mvel2.compiler.ExecutableAccessor.getValue(ExecutableAccessor.java:38)
at org.mvel2.ast.Substatement.getReducedValueAccelerated(Substatement.java:44)
at org.mvel2.ast.Union.getReducedValueAccelerated(Union.java:44)
at org.mvel2.compiler.ExecutableAccessor.getValue(ExecutableAccessor.java:38)
at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getMethod(ReflectiveAccessorOptimizer.java:970)
at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(ReflectiveAccessorOptimizer.java:396)
Thank you all.
Drools has a lot of built-in null checking, but if you insist on bypassing it you're going to end up with a lot of errors.
The other kind of interesting Drools has is a special syntax for maps -- get("foo") can be written as this["foo"].
rule "drools1"
when
Model( id == "1", // equivalent to getId().equals("1")
$map: map != null )
// Special syntax for getting stuff from maps:
Map( $param1: this["param1"] != null ) from $map
ParameterModel( $value: value != null ) from $param1
Integer( this > 10 ) from Integer.parseInt($value.toString())
then
System.out.println("Error on " + drools.getRule().getName());
end
Why was your version giving a NPE? Not a clue, but it was also just about unreadable in its original form. All that really can be gleaned from the stack trace was that it was occurring at some implicit conversion step.
Of course this version will also fail if value isn't something whose toString() turns into a String representation of an integer.
Note that if value is actually an Integer type, then you don't need to waste time with the parse int and can just do:
Integer(this > 10) from $value

Search nested object with spring data, Illegal attempt to dereference path source

I use spring data jpa, I have these classe (each one have id... not displayed)
public class HOV{
#ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
#JoinColumn(name = "vehicle_type_id")
private VehicleTypes vehicleType;
...
}
public class VehicleTypes{
#OneToMany(mappedBy = "vehicleType")
private List<Vehicles> vehicles = new ArrayList<>();
}
so in hov repository, i tried to search by vehiclesId
List<HOV> findByVehicleTypeVehiclesId(Integer id);
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'hOVRepository': Invocation of init
method failed; nested exception is java.lang.IllegalArgumentException:
Failed to create query for method public abstract java.util.List
com.lcm.repository.HOVRepository.findByVehicleTypeVehiclesId(java.lang.Integer)!
Illegal attempt to dereference path source [null.vehicleType.vehicles]
of basic type
In your situation, I think, is better to provide a query yourself, for example:
#Query("select h from HOV h join h.vehicleType vt left join vt.vehicles v where v.id = ?1")
List<HOV> findWithQuery(Integer vehicleId);

Saving value in Hibernate to another table than entity table

I have two tables bo_operator and hist_bo_operator_password. In bo_operator the id column is foreign key to hist_bo_operator_password and I can have many the same operator_id in hist_bo_operator_password and only one id in bo_operator.
My entity:
#Entity
#Table(name="bo_operator")
public class Operator implements Serializable
and that's how I am getting values from hist_bo_operator_password:
#ElementCollection
#CollectionTable(name="hist_bo_operator_password", joinColumns=#JoinColumn(name="id_operator"))
#Column(name="password")
public List<String> oldPasswords = new ArrayList<String>();
but when I'm trying to get only one value by:
#ElementCollection
#CollectionTable(name="hist_bo_operator_password", joinColumns=#JoinColumn(name="id_operator"))
#Column(name="password")
public String oldPassword;
I'm getting error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElements: local.vlex.operator.model.Operator.oldPassword
and all I want to do is makeing an insert into hist_bo_operator_password by
operator.setOldPassword(oldPassword);. I think the problem is that it doesn't know which password take if there is many values for the same id.
How to achive it?
#Edit
I also tried:
#Table(name="bo_operator")
#SecondaryTable(name = "hist_bo_operator_password",pkJoinColumns=#PrimaryKeyJoinColumn(name="id_operator", referencedColumnName="id"))
I even found ORDER BY so:
#Column(name="password", table="hist_bo_operator_password")
#OrderBy("data_ins")
public String oldPassword;
but seems like there is no #Limit or something like this in JPA and I still have many values to the same id which cause error:
org.hibernate.HibernateException: Duplicate identifier in table for: [local.vlex.operator.model.Operator#1]
As you described at the first sentence you have one-to-many relationship
#ElementCollection
#CollectionTable(name="hist_bo_operator_password", joinColumns=#JoinColumn(name="id_operator"))
#Column(name="password")
#OrderBy("data_ins")
public List<String> oldPasswords = new ArrayList<String>();
Then add necessary getter
Optional<String> getPassword() {
return oldPasswords.size() > 0
? Optional.of(oldPasswords.get(0))
: Optional.empty();
}
And setter
void setPassword(String password) { // or maybe addPassword?
oldPasswords.add(password);
}
Why don't you create entity of hist_bo_operator_password?
Then you could have List of that entities (instead of just String List) and just add another object to List and save entity Operator.

Entity bean 3.0 composite key issue

1: I have a table as shown below :
Name Null? Type
ATX_ID NOT NULL NUMBER(16)
ATX_GLM_CD NOT NULL NUMBER(5)
ATX_CRDR_FLG NOT NULL VARCHAR2(1)
ATX_AMT NOT NULL NUMBER(15,2)
ATX_STTS NOT NULL VARCHAR2(1)
ATX_TCM_ID NOT NULL NUMBER(16)
ATX_TXN_DT NOT NULL DATE
ATX_CRTE_BY NOT NULL VARCHAR2(30)
ATX_CRTE_DT NOT NULL DATE
The columns ATX_ID,ATX_GLM_CD and ATX_CRDR_FLG form a composite primary key.
2: I have created an entity bean class for the above table as follows :
#Entity
public class AcctngTxns implements Serializable {
private BigDecimal atxAmt;
private String atxStts;
private BigDecimal atxTcmId;
private Date atxTxnDt;
private String atxCrteBy;
private Date atxCrteDt;
#EmbeddedId
private AcctngTxnsPK acctngTxnsPK;
public AcctngTxns() {
//super();
}
/*getters and setters*/
}
#Embeddable
public class AcctngTxnsPK implements Serializable {
private long atxId;
private long atxGlmCd;
private String atxCrdrFlg;
private static final long serialVersionUID = 1L;
public AcctngTxnsPK() {
//super();
}
/*necessary overrides*/
}
3: /orm.xml/
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
version="1.0">
4: /persistence.xml/
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
DataSource
com.nseit.ncfm2.data.ejb.entity.AcctngTxns
5: While accessing the entity bean via a session bean,I am getting the following exception :
<[weblogic.servlet.internal.WebAppServletContext#1a1bc8f - appName: '_auto_generated_ear_', name: 'AWebApp', context-path: '/AWebApp', spec-version: '2.5'] Servlet failed with Exception
javax.ejb.EJBException: EJB Exception: ; nested exception is:
org.apache.openjpa.persistence.ArgumentException: Fields "com.nseit.ncfm2.data.ejb.entity.AcctngTxns.acctngTxnsPK" are not a default persistent type, and do not have any annotations indicating their persistence strategy. If you do not want these fields to be persisted, annotate them with #Transient.
at weblogic.ejb.container.internal.RemoteBusinessIntfProxy.unwrapRemoteException(RemoteBusinessIntfProxy.java:105)
at weblogic.ejb.container.internal.RemoteBusinessIntfProxy.invoke(RemoteBusinessIntfProxy.java:87)
at $Proxy127.gottaAccessEntity3(Unknown Source)
at jsp_servlet.__result.jspService(_result.java:115)
at weblogic.servlet.jsp.JspBase.service(JspBase.java:34)
Truncated. see log file for complete stacktrace
org.apache.openjpa.persistence.ArgumentException: Fields "com.nseit.ncfm2.data.ejb.entity.AcctngTxns.acctngTxnsPK" are not a default persistent type, and do not have any annotations indicating their persistence strategy. If you do not want these fields to be persisted, annotate them with #Transient.
at org.apache.openjpa.persistence.PersistenceMetaDataFactory.validateStrategies(PersistenceMetaDataFactory.java:399)
at org.apache.openjpa.persistence.PersistenceMetaDataFactory.load(PersistenceMetaDataFactory.java:205)
at org.apache.openjpa.meta.MetaDataRepository.getMetaDataInternal(MetaDataRepository.java:474)
at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:294)
at org.apache.openjpa.kernel.BrokerImpl.newObjectId(BrokerImpl.java:1114)
Truncated. see log file for complete stacktrace
7: Certainly,I do not want the primary key fields to be updated.
8: I tried to figure out the implementation of the below points mentioned in JPA documentation :
A composite primary key must be represented and mapped to multiple fields or properties of the entity class, or must be represented and mapped as an embeddable class.
If the class is mapped to multiple fields or properties of the entity class, the names and types of the primary key fields or properties in the primary key class must match those of the entity class.
8: Please help me in resolving the issue.
Thanks !
I found a solution by trial-and-error method. It seems that with JPA 1.0,it is necessary to mention the embedded-id in orm.xml file as follows :
Thanks.