[BAEL-1219] Code for Olingo V4 sample

This commit is contained in:
Philippe
2019-04-12 00:16:38 -03:00
parent 6ac9c01d3d
commit 270582b25a
12 changed files with 552 additions and 90 deletions
+1 -1
View File
@@ -52,7 +52,7 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.olingo</groupId>
<artifactId>odata-server-api</artifactId>
@@ -14,33 +14,22 @@ import org.springframework.context.annotation.Configuration;
@Configuration
public class ODataServiceConfiguration {
@Bean
public ServletRegistrationBean<HttpServlet> odataServletRegistration(ODataHttpHandlerFactory factory, EntityManagerFactory emf) {
ServletRegistrationBean bean = new ServletRegistrationBean(
odataServlet(factory,emf),
"/odata/*");
bean.setLoadOnStartup(1);
return bean;
}
@Bean
public HttpServlet odataServlet(ODataHttpHandlerFactory factory, EntityManagerFactory emf ) {
return new ODataServlet(factory,emf);
public ServletRegistrationBean<HttpServlet> odataServletRegistration(ODataHttpHandlerFactory factory) {
ServletRegistrationBean<HttpServlet> srb =
new ServletRegistrationBean<>(new ODataServlet(factory), "/odata/*");
srb.setLoadOnStartup(1);
return srb;
}
@Bean
public ODataHttpHandlerFactory httpHandlerFactory(CsdlEdmProvider edmProvider, ODataFactory odataFactory, List<Processor> processors) {
return new ODataHttpHandlerFactoryImplBuilder()
.edmProvider(edmProvider)
.odataFactory(odataFactory)
.processors(processors)
.build();
.edmProvider(edmProvider)
.odataFactory(odataFactory)
.processors(processors)
.build();
}
}
@@ -25,7 +25,7 @@ public class ODataServlet extends HttpServlet {
private final ODataHttpHandlerFactory odataHttpHandlerFactory;
public ODataServlet(ODataHttpHandlerFactory factory, EntityManagerFactory emf) {
public ODataServlet(ODataHttpHandlerFactory factory) {
this.odataHttpHandlerFactory = factory;
}
@@ -62,8 +62,9 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider {
if (e != null) {
CsdlEntitySet entitySet = new CsdlEntitySet();
entitySet.setName(entitySetName);
entitySet.setType(new FullQualifiedName(NAMESPACE, e.getName()));
entitySet
.setName(entitySetName)
.setType(new FullQualifiedName(NAMESPACE, e.getName()));
return entitySet;
}
}
@@ -135,7 +136,6 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider {
.map((e) -> {
try {
// Here we use a simple mapping strategy to map entity types to entity set names:
//
return getEntitySet(CONTAINER, e.getName() + "s");
} catch (ODataException oe) {
throw new RuntimeException(oe);
@@ -197,12 +197,22 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider {
result.setKey(ids);
// Process navs
// Process 1:N navs
List<CsdlNavigationProperty> navs = et.getDeclaredPluralAttributes()
.stream()
.map(attr -> buildNavAttribute(et, attr))
.collect(Collectors.toList());
result.setNavigationProperties(navs);
// Process N:1 navs
List<CsdlNavigationProperty> navs2 = et.getDeclaredSingularAttributes()
.stream()
.filter(attr -> attr.getPersistentAttributeType() == PersistentAttributeType.MANY_TO_ONE)
.map(attr -> buildNavAttribute(et, attr))
.collect(Collectors.toList());
result.getNavigationProperties().addAll(navs2);
return result;
}
@@ -225,13 +235,26 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider {
return p;
}
// Build NavProperty for 1:N or M:N associations
private CsdlNavigationProperty buildNavAttribute(EntityType<?> et, PluralAttribute<?, ?, ?> attr) {
CsdlNavigationProperty p = new CsdlNavigationProperty().setName(attr.getName())
.setType(new FullQualifiedName(NAMESPACE, attr.getBindableJavaType().getSimpleName()))
.setNullable(false); // for now
.setCollection(true)
.setNullable(false);
return p;
}
// Build NavProperty for N:1 associations
private CsdlNavigationProperty buildNavAttribute(EntityType<?> et, SingularAttribute<?, ?> attr) {
CsdlNavigationProperty p = new CsdlNavigationProperty().setName(attr.getName())
.setType(new FullQualifiedName(NAMESPACE, attr.getBindableJavaType().getSimpleName()))
.setCollection(false)
.setNullable(attr.isOptional());
return p;
}
}
@@ -48,10 +48,12 @@ public class JpaEntityCollectionProcessor implements CountEntityCollectionProces
private ServiceMetadata serviceMetadata;
private EntityManagerFactory emf;
private RepositoryRegistry repositoryRegistry;
private JpaEntityMapper entityMapper;
public JpaEntityCollectionProcessor(EntityManagerFactory emf, RepositoryRegistry repositoryRegistry) {
public JpaEntityCollectionProcessor(EntityManagerFactory emf, RepositoryRegistry repositoryRegistry, JpaEntityMapper entityMapper) {
this.emf = emf;
this.repositoryRegistry = repositoryRegistry;
this.entityMapper = entityMapper;
}
@Override
@@ -115,71 +117,40 @@ public class JpaEntityCollectionProcessor implements CountEntityCollectionProces
}
private EntityCollection getData(EdmEntitySet edmEntitySet, UriInfo uriInfo) {
/**
* Helper method to retrieve all entities of an entity set from an the backend database
* @param edmEntitySet
* @param uriInfo
* @return
*/
protected EntityCollection getData(EdmEntitySet edmEntitySet, UriInfo uriInfo) {
EdmEntityType type = edmEntitySet.getEntityType();
JpaRepository<?, ?> repo = repositoryRegistry.getRepositoryForEntity(type);
JpaRepository<?, ?> repo = (JpaRepository<?, ?>)repositoryRegistry.getRepositoryForEntity(type);
EntityCollection result = new EntityCollection();
repo.findAll()
.stream()
.forEach((it) -> result.getEntities()
.add(map2entity(edmEntitySet, it)));
.add(entityMapper.map2entity(edmEntitySet, it)));
return result;
}
private Entity map2entity(EdmEntitySet edmEntitySet, Object entry) {
EntityType<?> et = emf.getMetamodel()
.entity(entry.getClass());
Entity e = new Entity();
try {
// First, we set the entity's primary key
// Now map all properties
et.getDeclaredSingularAttributes().stream()
.forEach( (attr) -> {
if ( !attr.isAssociation()) {
Object v = getPropertyValue(entry,attr.getName());
Property p = new Property(null, attr.getName(),ValueType.PRIMITIVE,v);
e.addProperty(p);
if ( attr.isId()) {
e.setId(createId(edmEntitySet.getName(),v));
}
}
});
} catch (Exception ex) {
throw new ODataRuntimeException("[E141] Unable to create OData entity", ex);
}
return e;
}
private Object getPropertyValue(Object entry, String name) {
try {
return PropertyUtils.getProperty(entry,name);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new ODataRuntimeException("[E141] Unable to read property from entity, property=" + name, e);
}
}
private URI createId(String entitySetName, Object id) {
try {
return new URI(entitySetName + "(" + String.valueOf(id) + ")");
} catch (URISyntaxException e) {
throw new ODataRuntimeException("[E177] Unable to create URI", e);
}
}
/**
* Helper method to get the total size of an entity set
* @param edmEntitySet
* @param uriInfo
* @return
*/
private Long getCount(EdmEntitySet edmEntitySet, UriInfo uriInfo) {
// TODO Auto-generated method stub
return null;
EdmEntityType type = edmEntitySet.getEntityType();
JpaRepository<?, ?> repo = (JpaRepository<?, ?>)repositoryRegistry.getRepositoryForEntity(type);
EntityCollection result = new EntityCollection();
return repo.count();
}
}
@@ -0,0 +1,84 @@
/**
*
*/
package org.baeldung.examples.olingo4.processor;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;
import javax.persistence.EntityManagerFactory;
import javax.persistence.metamodel.EntityType;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.data.ValueType;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
import org.springframework.stereotype.Component;
/**
* <p>Helper class that converts a JPA entity into an OData entity using
* available metadata from the JPA's EntityManagerFactory.</p>
*
* @author Philippe
*
*/
@Component
public class JpaEntityMapper {
private EntityManagerFactory emf;
public JpaEntityMapper(EntityManagerFactory emf) {
this.emf = emf;
}
public Entity map2entity(EdmEntitySet edmEntitySet, Object entry) {
EntityType<?> et = emf.getMetamodel()
.entity(entry.getClass());
Entity e = new Entity();
try {
et.getDeclaredSingularAttributes().stream()
.forEach( (attr) -> {
if ( !attr.isAssociation()) {
Object v = getPropertyValue(entry,attr.getName());
Property p = new Property(null, attr.getName(),ValueType.PRIMITIVE,v);
e.addProperty(p);
if ( attr.isId()) {
e.setId(createId(edmEntitySet.getName(),v));
}
}
});
} catch (Exception ex) {
throw new ODataRuntimeException("[E141] Unable to create OData entity", ex);
}
return e;
}
private Object getPropertyValue(Object entry, String name) {
try {
return PropertyUtils.getProperty(entry,name);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new ODataRuntimeException("[E141] Unable to read property from entity, property=" + name, e);
}
}
private URI createId(String entitySetName, Object id) {
try {
return new URI(entitySetName + "(" + String.valueOf(id) + ")");
} catch (URISyntaxException e) {
throw new ODataRuntimeException("[E177] Unable to create URI", e);
}
}
}
@@ -6,7 +6,11 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
@Repository
public interface CarMakerRepository extends JpaRepository<CarMaker, Long>, JpaSpecificationExecutor<CarMaker>, EdmEntityRepository {
public interface CarMakerRepository extends EdmEntityRepository<CarMaker>, JpaRepository<CarMaker, Long>, JpaSpecificationExecutor<CarMaker> {
public default String getEdmEntityName() { return CarMaker.class.getSimpleName();}
@Override
default Class<CarMaker> getEntityClass() {
return CarMaker.class;
}
}
@@ -1,13 +1,22 @@
package org.baeldung.examples.olingo4.repository;
import java.util.List;
import org.baeldung.examples.olingo4.domain.CarModel;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
@Repository
public interface CarModelRepository extends JpaRepository<CarModel, Long>, JpaSpecificationExecutor<CarModel>,EdmEntityRepository {
public interface CarModelRepository extends EdmEntityRepository<CarModel>, JpaRepository<CarModel, Long>, JpaSpecificationExecutor<CarModel> {
public List<CarModel> findByMakerId(Long makerId);
public default String getEdmEntityName() { return CarModel.class.getSimpleName();}
@Override
default Class<CarModel> getEntityClass() {
return CarModel.class;
}
}
@@ -8,8 +8,10 @@ package org.baeldung.examples.olingo4.repository;
* @author Philippe
*
*/
public interface EdmEntityRepository {
public interface EdmEntityRepository<E> {
public String getEdmEntityName();
public Class<E> getEntityClass();
}
@@ -5,24 +5,23 @@ import java.util.List;
import java.util.Map;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
@Component
public class RepositoryRegistry {
private Map<String,JpaRepository<?,?>> repositoriesByClassName = new HashMap<>();
private Map<String,EdmEntityRepository<?>> repositoriesByClassName = new HashMap<>();
public RepositoryRegistry(List<EdmEntityRepository> allRepositories) {
public RepositoryRegistry(List<EdmEntityRepository<?>> allRepositories) {
allRepositories.stream().forEach((r) ->
repositoriesByClassName.put(r.getEdmEntityName(),(JpaRepository<?,?>)r));
repositoriesByClassName.put(r.getEdmEntityName(),(EdmEntityRepository<?>)r));
}
public JpaRepository<?, ?> getRepositoryForEntity(EdmEntityType entityType) {
JpaRepository<?, ?> repo = repositoriesByClassName.get(entityType.getName());
public EdmEntityRepository<?> getRepositoryForEntity(EdmEntityType entityType) {
EdmEntityRepository<?> repo = repositoriesByClassName.get(entityType.getName());
return repo;
}
}
@@ -1,3 +1,6 @@
server:
port: 8080
spring:
jpa:
show-sql: true