JPA Stored procedure NoSuchMethodError - maven

I'm following this JPA 2.1 StoredProcedureQuery as an example for what I'm working on.
Anyway, I have a Stored Procedure in the database named "XYZ" and I created a class:
#NameStoredProcedureQuery(
name = "createXYZ",
procedureName = "ZYX",
resultClasses = XYZObj.class,
parameters={
#StoredProcedureParameter(mode=ParameterMode.IN, name = "name", type = String.class),
#StoredProcedureParameter(mode=ParameterMode.OUT, name = "id", type = String.class)})
public class XYZObj {
private String id;
private String name;
...
}
Here is my DAO class:
#Stateless
public class XYZDAO{
#PersistenceContext(unitName = "PU")
private EntityManager em;
public String createXYZ(String name){
StoredProcedureQuery query = em.createNamedStoredProcedureQuery("createXYZ");
query.setParameter("name", name);
query.execute();
return query.getOutputParameterValue("id")
}
...
}
RESTFUL:
#Stateless
#Path("/XYZ")
public class XYZServlet{
#EJB
private XYZDAO xyzDao;
#GET
#Path("test")
public Response test(){
xyzDao.createXYZ("myname");
return Response.satus(Status.NO_CONTENT).build();
}
}
pom.xml
...
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.6.0-M3</version>
</dependency>
...
I'm getting NoSuchMethodError at this line.
StoredProcedureQuery query = em.createNamedStoredProcedureQuery("createXYZ");
Does anyone knows why? Am I using the right version of JPA? Did I miss something?
Here is the actual error that i'm getting.
java.lang.ClassCastException: java.lang.NoSuchMethodError cannot be cast to java.lang.exception
at javax.ejb.EJBException.getCauseByException(EJBException.java:23)
at com.sun.jersey.server.impl.ejb.EJBExceptionMapper.toResponse(EJBExceptionMapper.java:63)
at com.sun.jersey.server.impl.ejb.EJBExceptionMapper.toResponse(EJBExceptionMapper.java:54)
at com.sun.jersey.server.impl.ejb.EJBExceptionMapper.toResponse(EJBExceptionMapper.java:67)
at com.sun.jersey.server.impl.ejb.EJBExceptionMapper.toResponse(EJBExceptionMapper.java:54)
truncated. see log file for complete stacktrace
Thanks

Your project compilation looks like it's correctly referencing JPA 2.1, but a NoSuchMethodError indicates that the EntityManager available at runtime is from an earlier JPA version. The EntityManager is probably provided by your EJB container. Consult the documentation of whatever application server you are using to determine how to upgrade to JPA 2.1.
EDIT:
You should also mark whatever maven dependencies that are provided by your application server as <scope>provided</scope> in your pom.xml.

Related

Spring Data Neo4j MappingException: Field with primary id is null for entity

I have a node entity class that is extending an abstract class which is in turn extending another abstract class as follows:
public abstract class AbstractModel{
#Id
#GeneratedValue(strategy = UuidStrategy.class)
#Convert(UuidStringConverter.class)
protected UUID uuid;
}
public abstract class AbstractBayModel extends AbstractModel{
.....//more protected fields
}
public class Person extends AbstractBayModel{
private String name;
.//more code
.
.
}
#Service
//Has a reference to a repository
public class PersonService{
public void add(Person person){
repository.insert(person);
}
}
now when I invoke the service class's add() method, I am getting the following error.
org.neo4j.ogm.exception.core.MappingException: Field with primary id is null for entity model.Person#41a45331
I have tried to alter the service method as follows and still get the same error:
public void add(Person person){
person.setUuid(UUID.randomUUID();
repository.insert(person);
}
I am using the following spring dependencies
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
Would be mighty obliged if anyone can assist.
regards
I had a similar problem when I wanted to persist an entity with custom-object-properties.
Neo4j-OGM only supports
any primitive, boxed primitive, String or arrays thereof,
essentially anything that naturally fits into a Neo4j node property.
I replaced all properties with the supported analogs leaving id as the only non-naturally fitting field:
#Id #Convert(UuidStringConverter.class)
#GeneratedValue(strategy = UuidStrategy.class)
private UUID uuid;
It worked for me, I hope it helps someone else.

Setting date format output in spring rest with gson

I have a legacy application which uses Spring-Rest and Google-GSON (declared in pom.xml) for serializing/deserializing Objects. In one of these objects there's a java.util.Date property, I want to set the date format but I cannot find how to do it.
I can't even switch to Jackson because a colleague of mine uses it explicitly in a part of his code.
How can I set the date format in this scenario?
This application doesn't use Spring Boot. Everything I found for this problem is about Spring-boot + Jackson.
EDIT: I add some details. I have this Class:
#Entity
#Table(name="WEB_ELENCO_SCHEMI")
#IdClass(PK.class)
public class WebElencoSchemi implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="COD_ARCHIVIO_ARCAM")
private BigDecimal codArchivioArcam;
#Temporal(TemporalType.DATE)
#Column(name="DATA_AGGIORNAM")
private Date dataAggiornam;
...
}
And this repository:
public interface WebElencoSchemiRepository extends CrudRepository<WebElencoSchemi, BigDecimal> {
public List<WebElencoSchemi> findByCodArchivioArcam(BigDecimal codArchivioArcam);
I want to set the format of dataAggiornam JSON output. I'm using GSON as serializator/deserializator for Spring Rest, as defined in pom.xml.
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
I tried adding a spring.gson.date-format property in my properties file with no success.
I'm NOT using Spring boot and I cannot switch to Jackson (in which the problem is solved with a simple annotation on the class property).
You can set a date format while creating the Gson object with the GsonBuilder.
Something like;
Gson gson = new GsonBuilder().setDateFormat("dd/MM/yyyy HH:mm").serializeNulls().create();
It has a bunch of other factory methods which are super useful also, for your perusal. Love this library.

How to map user data type in cassandra using spring boot data

I am looking out for some help related with spring boot data using Cassandra database.
I have following dependencies in my pom.xml.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-boot-starter-data-cassandra</artifactId>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>2.1.10.3</version>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-mapping</artifactId>
<version>2.1.10.3</version>
</dependency>
The table structure looks like:
#Table(value = "TEST_ORDERS")
public class OrderDTO {
#PrimaryKey
#Column(value = "email")
private String emailId;
#Column(value = "order_id")
private int orderId;
#Column(value = "creation_date")
private Timestamp creationDate;
#Column(value = "discount_total")
private double discountTotal;
#Column(name = "shipments")
//This is a UDT type
private Set<ShippingDetails> shipments;
//getters and setters here
}
The ShippingDetails object is a UDT with following declartion and i defined as a frozen collection in the cassandra CQL sripts
#UDT(name = "shipping", keyspace = "mc_checkout")
public class ShippingDetails {
#Field(name = "name")
private FullName name;
#Field(name = "quantity_shipped")
private int quantityShipped;
#Field(name = "shipping_address")
private CheckoutAddress shippingAddress;
//so on
}
There is a repository created for the basic CRUD operations:
#Repository
public interface OrderRepository extends CrudRepository<OrderDTO, String> {
}
When i try to invoke findOne API of this repository in my Service class
i get below error:
Cassandra entities must have the #Table, #Persistent or #PrimaryKeyClass Annotation
Spring Data for Apache Cassandra and Datastax' Mapping are two independent tools that try to accomplish the same. Please use either one but don't mix these.
CrudRepository is a Spring Data type while #Field and #UDT are coming from Datastax Mapping.
UDT support for Spring Data for Apache Cassandra is available as of version 1.5, see reference docs. Spring Data for Apache Cassandra 1.5 requires Datastax Java Driver 3.0 or newer.

How should I create H2 using SpringBoot?

I'm starting to play with Spring Boot and as part of that I want to create an in memory DB to work with and bootstrap with the application.
Given the config/code below I get no errors in the startup log and can access the application ok, so it does startup (I get template errors about objects not existing), but I don't get any data back from the DAO when calling findAll() (or if I try to call findById(int) ).
So while it seems things are ok (no error in log, log shows it finds the sql to create schema ad attempts to run the data.sql statements) when I try to access data via the DAO I get no Exception, but no data returned.
Any ideas or observations on the code that might be a problem?
I've added the Spring Data / H2 stuff to my pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
Spring DAO:
public interface PersonDao extends CrudRepository<Person, Integer> {
}
DB props in application.properties:
server.contextPath=/
server.port=8080
spring.mvc.view.suffix=.ftl
datasource.mine.jdbcUrl=jdbc:h2:tcp://localhost/mem:clubmanagement
datasource.mine.user=sa
datasource.mine.password=
datasource.mine.poolSize=30
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=DEBUG
spring.jpa.hibernate.ddl-auto=create
My service:
#Service
public class MemberServiceImpl implements MemberService {
#Autowired
PersonDao dao;
#Override
public Optional<ClubMember> getClubMember(int id) {
Person dbPerson = dao.findOne(id);
if(dbPerson == null) {
return Optional.empty();
}
return Optional.of(fromEntity(dbPerson));
}
#Override
public List<ClubMember> allMembers() {
Iterable<Person> people = dao.findAll();
List<ClubMember> members = new ArrayList<>();
people.forEach(person -> {
members.add(fromEntity(person));
});
return members;
}
private ClubMember fromEntity(Person p) {
ClubMember member = new ClubMember();
member.setCurrentGrade(p.getCurrentGrade());
member.setFirstName(p.getFirstName());
member.setLastName(p.getLastName());
member.setAssociationMemberId(p.getAssociationMemberId());
member.setLastGradingDate(p.getLastGradingDate());
return member;
}
}
Schema.sql in resources/ :
create table CLUB
(id int not null, name varchar(60), association_member_id int);
create table PERSON
(
id int not null, grade_id int, first_name varchar(35), last_name varchar(35),
association_membership varchar(12), last_grading_date date
);
create table GRADE
(id int not null, name varchar(20));
In data.sql (again in resources directory):
insert into club (id, name, association_member_id) values (1, 'some club', '123');
insert into person (id, grade_id, first_name, last_name, association_membership, last_grading_date)
values (1, 1, 'name', 'lastname', 'a1234', '2016-03-23');
Entity class I am trying to retrieve (Trying to use Lombock, also new to me, to generate getters/setters):
#Entity
#Table(name = "person")
public #Data class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private int id;
#JoinColumn(name = "grade_id")
private GRADE currentGrade;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "association_membership")
private String associationMemberId;
#Column(name = "last_grading_date")
#Temporal(value = TemporalType.DATE)
private Date lastGradingDate;
}
you want to add H2 database, but you added HSQLDB, please replace
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
with
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
EDIT
I noticed you have multiple issues in your code:
default schema file name is schema.sql not Schema.sql
names of tables in schema.sql are different than names in data.sql (PERSON vs person)
you used this spring.jpa.hibernate.ddl-auto=create in application.properties (default option), in this case JPA databases schema only will be automatically created (without data creation), so data.sql will not be executed, to fix this issues you can use validate or update option
I will write one simple example how to use H2 database with spring boot and JPA
This is the project structure:
Grade Entity
package com.shijazi;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="GRADE")
public class Grade {
#Id
#GeneratedValue
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Grade(int id, String name) {
super();
this.id = id;
this.name = name;
}
public Grade() {
}
}
GradeRepository.java
package com.shijazi;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface GradeRepository extends JpaRepository<Grade, Integer> {
}
Application.java
#SpringBootApplication
#RestController
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Autowired
private GradeRepository gradeRepo;
#RequestMapping(value="api/test")
public List<Grade> getall()
{
return gradeRepo.findAll();
}
}
application.properties
spring.jpa.hibernate.ddl-auto=validate
schema.sql
create table GRADE (id int not null, name varchar(20));
data.sql
insert into GRADE (id, name) values (2, 'name');
Dependencies in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Now just run application and call this URL: http://localhost:8080/api/test
try to change the spring.jpa.hibernate.ddl-auto and see results
if you activate ddl-auto and have a schema.sql, BOTH of them are executed. But normally schema.sql is executed first. So the ddl-auto throws everything away, which was created by schema.sql and data.sql
After spending some time working through some ideas with #Safwan Hijazi in chat, came to the conclusion that what is happening is that the schema.sql and data.sql were being run but then the schema was recreated depending on the value (or lack of) of the spring.jpa.hibernate.ddl-auto property.
If not specified, spring/hibernate between them ended up recreating an empty schema (default seems to be create-drop for in memory DB).
If set the 'none' then that wouldn't happen and DB as created by the schema and data sql scripts would remain and the application functioned correctly.
See also: CrudRepository not reading data from schema.sql
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Just gives you an spring boot opinionated inclusion to the spring-boot-starter-data-jpa maven file, for the bill of material of all the dependencies. To use any one of the dependency defined in the Dependency management of the spring-boot-starter-data-jpa pom you will have to explicitly declare the dependency in dependency section of your pom file.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
To get the h2 database up and running with your application, you can specifiy the properties in your application.properties file at src/main/resources/application.properties use:
spring.h2.console.enabled=true
spring.h2.console.path=/h2DB
so when you run your application with spring application starter, you will be able to access the application at http://localhost:8080/h2DB login to the DB and you can verify if the database had the inserts in it or not?
Don't find the data in there then you know where to make a change to keep the data there.

#JsonIgnore is ignored in JUnit-Controller-Unit Test with Mockito

i have constructed my first Spring-Controller Unit Tests and one Controller gives back one object in JSON-Format. The Relations are annotated with #JsonIgnore and it works in my software.
When I simply wanna test those Controllers I'll always get an infinite-Recursion Error on exactly that attribute. It's a 1:1 Relation. On other relations the #JsonIgnore works without any problems.
Tests in error:
save(package.a.b.c.test.ControllerATest): Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError) (through reference chain: package.a.b.c.entity.A["b"]->package.a.b.c.B["a"] etc...
It seems, like my #JsonIgnore is ignored in test-scope?
It's a Maven-managed Project, so i include like this
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
Maybe, somebody made the same experience?
Is the annotation on the fields or their getters? Jackson only looks at the getters by default so moving your annotation to the getters will solve the problem. For example:
class Person {
#JsonIgnore
Set<Department> departments;
public Set<Department> getDepartments() { return this.departments; }
}
class Department {
#JsonIgnore
Set<Person> persons;
public Set<Person> getPersons() return this.persons; }
}
will cause an infinite recursion if a Person and a Department object are referencing each other.
The following will work:
class Person {
Set<Department> departments;
#JsonIgnore
public Set<Department> getDepartments() { return this.departments; }
}
class Department {
Set<Person> persons;
#JsonIgnore
public Set<Person> getPersons() return this.persons; }
}
i just found out, it has to do with bi-directional 1:1 relationships in objects. Switching to newer Version 2.3.1, provided with the following dependencies, solved that issue:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.3.1</version>
</dependency>

Resources