Vote count:
0
I have a simple proof-of-concept demo using Spring Data REST / RestRepository architecture. My two entities are :
@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="Address")
public class Address implements Serializable {
public Address() {
}
@Column(name="ID", nullable=false, unique=true)
@Id
@GeneratedValue(generator="COM_COMPORIUM_CUSTOMER_ADDRESSES_ADDRESS_ID_GENERATOR")
@org.hibernate.annotations.GenericGenerator(name="COM_COMPORIUM_CUSTOMER_ADDRESSES_ADDRESS_ID_GENERATOR", strategy="native")
private int ID;
@RestResource(exported = false)
@ManyToOne(targetEntity=com.comporium.domain.location.CityStateZip.class, fetch=FetchType.LAZY)
@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.PERSIST})
@JoinColumns({ @JoinColumn(name="CityStateZipID", referencedColumnName="ID", nullable=false) })
private com.comporium.domain.location.CityStateZip cityStateZip;
@Column(name="StreetNo", nullable=true)
private int streetNo;
@Column(name="StreetName", nullable=false, length=40)
private String streetName;
<setters and getters ommitted>
}
and for CityStateZip:
@Entity
public class CityStateZip {
public CityStateZip() {
}
@Column(name="ID", nullable=false, unique=true)
@Id
@GeneratedValue(generator="COM_COMPORIUM_CUSTOMER_ADDRESSES_CITYSTATEZIP_ID_GENERATOR")
@org.hibernate.annotations.GenericGenerator(name="COM_COMPORIUM_CUSTOMER_ADDRESSES_CITYSTATEZIP_ID_GENERATOR", strategy="native")
private int ID;
@Column(name="ZipCode", nullable=false, length=10)
private String zipCode;
@Column(name="City", nullable=false, length=24)
private String city;
@Column(name="StateProv", nullable=false, length=2)
private String stateProv;
}
with repositories:
@RepositoryRestResource(collectionResourceRel = "addr", path = "addr")
// w/o annotation, this publishes at /addresses/search
public interface AddressRepository extends JpaRepository<Address, Integer> {
List<Address> findByStreetNoAndStreetNameStartingWithIgnoreCase(@Param("stNumber") Integer streetNo, @Param("street") String streetName);
List<Address> findByStreetNameStartingWithIgnoreCase(@Param("street") String streetName);
List<Address> findByStreetNo(@Param("streetNo") Integer strNo);
}
and:
//@RepositoryRestResource(collectionResourceRel = "zip", path = "zip", exported = false)
@RepositoryRestResource(collectionResourceRel = "zip", path = "zip")
public interface CityStateZipRepository extends JpaRepository<CityStateZip, Integer> {
public List<CityStateZip> findByZipCode(@Param("zipCode") String zipCode);
public List<CityStateZip> findByStateProv(@Param("stateProv") String stateProv);
public List<CityStateZip> findByCityAndStateProv(@Param("city") String city, @Param("state") String state);
}
and main() code of
@Configuration
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
//@EnableTransactionManagement
@PropertySource(value = { "file:/etc/comporium/com.comporium.domain.location/application.properties" })
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
with this code, I can save a CSZ by POSTing this JSON to http://ift.tt/121uuqv:
{ "zipCode" : "28899" , "city" : "Ada", "stateProv" : "NC" }
but if I try to save an Address by POSTing the JSON to .../addr:
{ "streetNo" : "985" , "streetName" : "Bellingham", "plus4Zip" : 2212, "cityStateZip" : { "zipCode" : "28115" , "city" : "Mooresville", "stateProv" : "NC" } }
I get the error
{
"cause": {
"cause": {
"cause": null,
"message": "Template must not be null or empty!"
},
"message": "Template must not be null or empty! (through reference chain: com.comporium.domain.location.Address[\"cityStateZip\"])"
},
"message": "Could not read JSON: Template must not be null or empty! (through reference chain: com.comporium.domain.location.Address[\"cityStateZip\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Template must not be null or empty! (through reference chain: com.comporium.domain.location.Address[\"cityStateZip\"])"
}
Now if I change CityStateZipRepository to include "export=false" in the annotation, I can then save the Address and CSZ to the database. But at that time, .../zip is no longer exposed on the interface, AND doing GET .../addr or .../addr/{id} causes this error:
{
"timestamp": 1417728145384,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.http.converter.HttpMessageNotWritableException",
"message": "Could not write JSON: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.springframework.hateoas.PagedResources[\"_embedded\"]->java.util.UnmodifiableMap[\"addr\"]->java.util.ArrayList[0]->org.springframework.hateoas.Resource[\"content\"]->com.comporium.domain.location.Address[\"cityStateZip\"]->com.comporium.domain.location.CityStateZip_$$_jvst4e0_0[\"handler\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.springframework.hateoas.PagedResources[\"_embedded\"]->java.util.UnmodifiableMap[\"addr\"]->java.util.ArrayList[0]->org.springframework.hateoas.Resource[\"content\"]->com.comporium.domain.location.Address[\"cityStateZip\"]->com.comporium.domain.location.CityStateZip_$$_jvst4e0_0[\"handler\"])",
"path": "/addr"
}
Isa there a way to set up this model to be able to POST and GET from this database? Also, the JOSN passed to Address will save a new instance of CityStateZip - what format will allow us to reference an existing CityStateZip element?
Thanks for any help you can provide - this has been driving us crazy for days now.
GETing and POSTing nested entities in RestRepository
Aucun commentaire:
Enregistrer un commentaire