Java – unable to get JPA entity ID in JSON output
We are trying to use the POC of spring data JPA and spring data rest
We are using a simple entity that extends abstractpersistent (which is a spring data JPA class) http://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/domain/AbstractPersistable.html ).
This is the source code of this one:
@MappedSuperclass
public abstract class AbstractPersistable<PK extends Serializable> implements Persistable<PK> {
private static final long serialVersionUID = -5554308939380869754L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private PK id;
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Persistable#getId()
*/
public PK getId() {
return id;
}
/**
* Sets the id of the entity.
*
* @param id the id to set
*/
protected void setId(final PK id) {
this.id = id;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Persistable#isNew()
*/
public boolean isNew() {
return null == getId();
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return String.format("Entity of type %s with id: %s",this.getClass().getName(),getId());
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (null == obj) {
return false;
}
if (this == obj) {
return true;
}
if (!getClass().equals(obj.getClass())) {
return false;
}
AbstractPersistable<?> that = (AbstractPersistable<?>) obj;
return null == this.getId() ? false : this.getId().equals(that.getId());
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int hashCode = 17;
hashCode += null == getId() ? 0 : getId().hashCode() * 31;
return hashCode;
}
}
And our entities:
@Entity
@Table(name = "TEST_ENTITY")
public class TestEntity extends AbstractPersistable<Long> {
@Column(name = "TITLE",nullable = false,length = 100)
private String title;
@Column(name = "DESCRIPTION",length = 500)
private String description;
@ManyToOne(fetch = FetchType.LAZY,optional = false)
@JoinColumn(name = "GLOBAL_DATATYPE_ID",referencedColumnName = "ID",updatable = false)
private globalDataType dataType;
@Enumerated(EnumType.STRING)
@Column(name = "VALUE_TYPE",length = 30)
private ValueType valueType;
@Enumerated(EnumType.STRING)
@Column(name = "ATTRIBUTE_TYPE",length = 30)
private AttributeType attributeType;
@Column(name = "FE_DISPLAY")
@Convert(converter=BooleanTFConverter.class)
private Boolean feDisplay;
{... getter setter equals hashcode toString ...}
}
Then the service (using spring data rest):
@RepositoryRestResource(path = "test")
public interface TestEntityRepository extends JpaRepository<TestEntity,Long> {
}
We use spring to launch and run the application. The output on chrome (URL: http: / / localhost: 8080 / test) is JSON Hal data (ID!!!):
{
"_links" : {
"self" : {
"href" : "http://localhost:8080/test{?page,size,sort}","templated" : true
}
},"_embedded" : {
"testEntities" : [ {
"title" : "Test","description" : "TEST","valueType" : "SINGLE","attributeType" : "ATTRIBUTE","feDisplay" : true,"new" : false,"_links" : {
"self" : {
"href" : "http://localhost:8080/test/1"
},"dataType" : {
"href" : "http://localhost:8080/test/1/dataType"
}
}
} ]
},"page" : {
"size" : 20,"totalElements" : 1,"totalPages" : 1,"number" : 0
}
}
The other thing is when we're in testentity( http://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/domain/AbstractAuditable.html )When abstractauditable is used on, it works. We get the field value from abstractauditable, but we still don't get the id
@Entity
@Table(name = "TEST_ENTITY")
public class TestEntity extends AbstractAuditable<User,Long> {
...
}
@MappedSuperclass
public abstract class AbstractAuditable<U,PK extends Serializable> extends AbstractPersistable<PK> implements
Auditable<U,PK> {
private static final long serialVersionUID = 141481953116476081L;
@ManyToOne(fetch = FetchType.LAZY,optional = false)
@JoinColumn(name = "CREATED_BY",updatable = false)
private U createdBy;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "CREATED_DATE")
private Date createdDate;
@ManyToOne(fetch = FetchType.LAZY,optional = false)
@JoinColumn(name = "LAST_MODIFIED_BY",updatable = false)
private U lastModifiedBy;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "LAST_MODIFIED_DATE")
private Date lastModifiedDate;
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Auditable#getCreatedBy()
*/
public U getCreatedBy() {
return createdBy;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.domain.Auditable#setCreatedBy(java.lang.Object)
*/
public void setCreatedBy(final U createdBy) {
this.createdBy = createdBy;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Auditable#getCreatedDate()
*/
public DateTime getCreatedDate() {
return null == createdDate ? null : new DateTime(createdDate);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.domain.Auditable#setCreatedDate(org.joda.time
* .DateTime)
*/
public void setCreatedDate(final DateTime createdDate) {
this.createdDate = null == createdDate ? null : createdDate.toDate();
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Auditable#getLastModifiedBy()
*/
public U getLastModifiedBy() {
return lastModifiedBy;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.domain.Auditable#setLastModifiedBy(java.lang
* .Object)
*/
public void setLastModifiedBy(final U lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Auditable#getLastModifiedDate()
*/
public DateTime getLastModifiedDate() {
return null == lastModifiedDate ? null : new DateTime(lastModifiedDate);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.domain.Auditable#setLastModifiedDate(org.joda
* .time.DateTime)
*/
public void setLastModifiedDate(final DateTime lastModifiedDate) {
this.lastModifiedDate = null == lastModifiedDate ? null : lastModifiedDate.toDate();
}
}
JSON Hal results:
{
"_links" : {
"self" : {
"href" : "http://localhost:8080/test{?page,"_embedded" : {
"testEntities" : [ {
"createdBy" : {
"username" : "xxx.admin"
},"createdDate" : {
"year" : 2014,"era" : 1,"dayOfYear" : 282,"dayOfWeek" : 4,"dayOfMonth" : 9,"weekOfWeekyear" : 41,"monthOfYear" : 10,"yearOfEra" : 2014,"yearOfCentury" : 14,"centuryOfEra" : 20,"weekyear" : 2014,"millisOfSecond" : 0,"millisOfDay" : 65724000,"secondOfMinute" : 24,"secondOfDay" : 65724,"minuteOfHour" : 15,"minuteOfDay" : 1095,"hourOfDay" : 18,"chronology" : {
"zone" : {
"fixed" : false,"uncachedZone" : {
"cachable" : true,"fixed" : false,"id" : "Europe/London"
},"id" : "Europe/London"
}
},"zone" : {
"fixed" : false,"uncachedZone" : {
"cachable" : true,"id" : "Europe/London"
},"id" : "Europe/London"
},"millis" : 1412874924000,"afterNow" : false,"beforeNow" : true,"equalNow" : false
},"lastModifiedBy" : null,"lastModifiedDate" : {
"year" : 2014,"millisOfDay" : 65731000,"secondOfMinute" : 31,"secondOfDay" : 65731,"millis" : 1412874931000,"title" : "Test","number" : 0
}
}
Editing: Solutions
Add custom repositoryrestmvcconfiguration
@Configuration
public class MyRepositoryRestMvcConfiguration extends RepositoryRestMvcConfiguration {
protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(TestEntity.class);
}
}
Then change @ import in your application Java configuration class
Before:
@Configuration
@EnableTransactionManagement
@Import(RepositoryRestMvcConfiguration.class)
@EnableJpaRepositories(basePackages="uk.co.xxx.marketplace.data.repository")
@PropertySources({@PropertySource("classpath:hibernate.properties"),@PropertySource("classpath:persistence.properties")})
@ComponentScan(value = "uk.co.xxx.marketplace.data")
@EnableAutoConfiguration
public class Application {
...
}
actual:
@Configuration
@EnableTransactionManagement
@Import(MyRepositoryRestMvcConfiguration.class)
@EnableJpaRepositories(basePackages="uk.co.xxx.marketplace.data.repository")
@PropertySources({@PropertySource("classpath:hibernate.properties"),@PropertySource("classpath:persistence.properties")})
@ComponentScan(value = "uk.co.xxx.marketplace.data")
@EnableAutoConfiguration
public class Application {
...
}
Solution
You can inherit the class repositoryrestconfiguration (or repositoryrestmvcconfiguration, if spring MVC is used), and call the method exposeidsfor () with the domain class you want to expose the ID
