Initial import
This commit is contained in:
parent
881580f2fe
commit
6ac9c01d3d
@ -19,10 +19,13 @@ import javax.persistence.criteria.CriteriaDelete;
|
|||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
import javax.persistence.criteria.CriteriaUpdate;
|
import javax.persistence.criteria.CriteriaUpdate;
|
||||||
import javax.persistence.metamodel.Metamodel;
|
import javax.persistence.metamodel.Metamodel;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.olingo.odata2.api.processor.ODataContext;
|
||||||
import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
|
import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
|
||||||
import org.apache.olingo.odata2.jpa.processor.api.ODataJPAServiceFactory;
|
import org.apache.olingo.odata2.jpa.processor.api.ODataJPAServiceFactory;
|
||||||
import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
|
import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
|
||||||
|
import org.baeldung.examples.olingo2.JerseyConfig.EntityManagerFilter;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
|
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
|
||||||
@ -44,7 +47,6 @@ public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory {
|
|||||||
setDetailErrors(true);
|
setDetailErrors(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will be called by Olingo on every request to
|
* This method will be called by Olingo on every request to
|
||||||
* initialize the ODataJPAContext that will be used.
|
* initialize the ODataJPAContext that will be used.
|
||||||
@ -54,18 +56,18 @@ public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory {
|
|||||||
|
|
||||||
log.info("[I32] >>> initializeODataJPAContext()");
|
log.info("[I32] >>> initializeODataJPAContext()");
|
||||||
ODataJPAContext ctx = getODataJPAContext();
|
ODataJPAContext ctx = getODataJPAContext();
|
||||||
|
ODataContext octx = ctx.getODataContext();
|
||||||
|
HttpServletRequest request = (HttpServletRequest)octx.getParameter(ODataContext.HTTP_SERVLET_REQUEST_OBJECT);
|
||||||
|
EntityManager em = (EntityManager)request.getAttribute(EntityManagerFilter.EM_REQUEST_ATTRIBUTE);
|
||||||
|
|
||||||
// Here we're passing the EM that was created by the EntityManagerFilter (see JerseyConfig)
|
// Here we're passing the EM that was created by the EntityManagerFilter (see JerseyConfig)
|
||||||
ctx.setEntityManager(new EntityManagerWrapper(EntityManagerHolder.getCurrentEntityManager()));
|
ctx.setEntityManager(new EntityManagerWrapper(em));
|
||||||
ctx.setPersistenceUnitName("default");
|
ctx.setPersistenceUnitName("default");
|
||||||
|
|
||||||
// We're managing the EM's lifecycle, so we must inform Olingo that it should not
|
// We're managing the EM's lifecycle, so we must inform Olingo that it should not
|
||||||
// try to manage transactions and/or persistence sessions
|
// try to manage transactions and/or persistence sessions
|
||||||
ctx.setContainerManaged(true);
|
ctx.setContainerManaged(true);
|
||||||
|
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class EntityManagerWrapper implements EntityManager {
|
static class EntityManagerWrapper implements EntityManager {
|
||||||
@ -73,18 +75,21 @@ public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory {
|
|||||||
private EntityManager delegate;
|
private EntityManager delegate;
|
||||||
|
|
||||||
public void persist(Object entity) {
|
public void persist(Object entity) {
|
||||||
log.info("[I68] persist: entity.class=" + entity.getClass().getSimpleName());
|
log.info("[I68] persist: entity.class=" + entity.getClass()
|
||||||
|
.getSimpleName());
|
||||||
delegate.persist(entity);
|
delegate.persist(entity);
|
||||||
//delegate.flush();
|
// delegate.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T merge(T entity) {
|
public <T> T merge(T entity) {
|
||||||
log.info("[I74] merge: entity.class=" + entity.getClass().getSimpleName());
|
log.info("[I74] merge: entity.class=" + entity.getClass()
|
||||||
|
.getSimpleName());
|
||||||
return delegate.merge(entity);
|
return delegate.merge(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(Object entity) {
|
public void remove(Object entity) {
|
||||||
log.info("[I78] remove: entity.class=" + entity.getClass().getSimpleName());
|
log.info("[I78] remove: entity.class=" + entity.getClass()
|
||||||
|
.getSimpleName());
|
||||||
delegate.remove(entity);
|
delegate.remove(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
package org.baeldung.examples.olingo2;
|
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
|
||||||
|
|
||||||
public class EntityManagerHolder {
|
|
||||||
|
|
||||||
private static ThreadLocal<EntityManager> currentEntityManager = new ThreadLocal<>();
|
|
||||||
|
|
||||||
|
|
||||||
public static void setCurrentEntityManager(EntityManager em) {
|
|
||||||
currentEntityManager.set(em);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static EntityManager getCurrentEntityManager() {
|
|
||||||
return currentEntityManager.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.baeldung.examples.olingo2;
|
package org.baeldung.examples.olingo2;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -6,12 +6,14 @@ import javax.persistence.EntityManager;
|
|||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
import javax.persistence.EntityTransaction;
|
import javax.persistence.EntityTransaction;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.ApplicationPath;
|
import javax.ws.rs.ApplicationPath;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.container.ContainerRequestContext;
|
import javax.ws.rs.container.ContainerRequestContext;
|
||||||
import javax.ws.rs.container.ContainerRequestFilter;
|
import javax.ws.rs.container.ContainerRequestFilter;
|
||||||
import javax.ws.rs.container.ContainerResponseContext;
|
import javax.ws.rs.container.ContainerResponseContext;
|
||||||
import javax.ws.rs.container.ContainerResponseFilter;
|
import javax.ws.rs.container.ContainerResponseFilter;
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.ext.Provider;
|
import javax.ws.rs.ext.Provider;
|
||||||
|
|
||||||
import org.apache.olingo.odata2.api.ODataServiceFactory;
|
import org.apache.olingo.odata2.api.ODataServiceFactory;
|
||||||
@ -59,9 +61,13 @@ public class JerseyConfig extends ResourceConfig {
|
|||||||
public static class EntityManagerFilter implements ContainerRequestFilter, ContainerResponseFilter {
|
public static class EntityManagerFilter implements ContainerRequestFilter, ContainerResponseFilter {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(EntityManagerFilter.class);
|
private static final Logger log = LoggerFactory.getLogger(EntityManagerFilter.class);
|
||||||
|
public static final String EM_REQUEST_ATTRIBUTE = EntityManagerFilter.class.getName() + "_ENTITY_MANAGER";
|
||||||
|
|
||||||
private final EntityManagerFactory emf;
|
private final EntityManagerFactory emf;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
private HttpServletRequest httpRequest;
|
||||||
|
|
||||||
public EntityManagerFilter(EntityManagerFactory emf) {
|
public EntityManagerFilter(EntityManagerFactory emf) {
|
||||||
this.emf = emf;
|
this.emf = emf;
|
||||||
}
|
}
|
||||||
@ -70,11 +76,12 @@ public class JerseyConfig extends ResourceConfig {
|
|||||||
public void filter(ContainerRequestContext ctx) throws IOException {
|
public void filter(ContainerRequestContext ctx) throws IOException {
|
||||||
log.info("[I60] >>> filter");
|
log.info("[I60] >>> filter");
|
||||||
EntityManager em = this.emf.createEntityManager();
|
EntityManager em = this.emf.createEntityManager();
|
||||||
EntityManagerHolder.setCurrentEntityManager(em);
|
httpRequest.setAttribute(EM_REQUEST_ATTRIBUTE, em);
|
||||||
|
|
||||||
// Start a new transaction unless we have a simple GET
|
// Start a new transaction unless we have a simple GET
|
||||||
if ( !"GET".equalsIgnoreCase(ctx.getMethod())) {
|
if (!"GET".equalsIgnoreCase(ctx.getMethod())) {
|
||||||
em.getTransaction().begin();
|
em.getTransaction()
|
||||||
|
.begin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,12 +89,12 @@ public class JerseyConfig extends ResourceConfig {
|
|||||||
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
|
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
|
||||||
|
|
||||||
log.info("[I68] <<< filter");
|
log.info("[I68] <<< filter");
|
||||||
|
EntityManager em = (EntityManager) httpRequest.getAttribute(EM_REQUEST_ATTRIBUTE);
|
||||||
|
|
||||||
EntityManager em = EntityManagerHolder.getCurrentEntityManager();
|
if (!"GET".equalsIgnoreCase(requestContext.getMethod())) {
|
||||||
if ( em != null && !"GET".equalsIgnoreCase(requestContext.getMethod())) {
|
|
||||||
EntityTransaction t = em.getTransaction();
|
EntityTransaction t = em.getTransaction();
|
||||||
if ( t.isActive()) {
|
if (t.isActive()) {
|
||||||
if ( !t.getRollbackOnly()) {
|
if (!t.getRollbackOnly()) {
|
||||||
t.commit();
|
t.commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,7 +106,6 @@ public class JerseyConfig extends ResourceConfig {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Path("/")
|
@Path("/")
|
||||||
public static class CarsRootLocator extends ODataRootLocator {
|
public static class CarsRootLocator extends ODataRootLocator {
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
server:
|
||||||
|
port: 8180
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
jersey:
|
jersey:
|
||||||
|
29
apache-olingo/olingo4/.gitignore
vendored
Normal file
29
apache-olingo/olingo4/.gitignore
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
HELP.md
|
||||||
|
/target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
95
apache-olingo/olingo4/pom.xml
Normal file
95
apache-olingo/olingo4/pom.xml
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.1.3.RELEASE</version>
|
||||||
|
<relativePath /> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
<groupId>org.baeldung.examples.olingo4</groupId>
|
||||||
|
<artifactId>olingo4-sample</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>olingo4-sample</name>
|
||||||
|
<description>Sample Olingo 4 Project</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<odata.version>4.5.0</odata.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.olingo</groupId>
|
||||||
|
<artifactId>odata-server-api</artifactId>
|
||||||
|
<version>${odata.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.olingo</groupId>
|
||||||
|
<artifactId>odata-server-core</artifactId>
|
||||||
|
<version>${odata.version}</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.olingo</groupId>
|
||||||
|
<artifactId>odata-commons-api</artifactId>
|
||||||
|
<version>${odata.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.olingo</groupId>
|
||||||
|
<artifactId>odata-commons-core</artifactId>
|
||||||
|
<version>${odata.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-beanutils</groupId>
|
||||||
|
<artifactId>commons-beanutils</artifactId>
|
||||||
|
<version>1.9.3</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,20 @@
|
|||||||
|
package org.baeldung.examples.olingo4;
|
||||||
|
|
||||||
|
import org.apache.olingo.server.api.OData;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation for ODataFactory
|
||||||
|
* @author Philippe
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class DefaultODataFactory implements ODataFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OData newInstance() {
|
||||||
|
return OData.newInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package org.baeldung.examples.olingo4;
|
||||||
|
|
||||||
|
import org.apache.olingo.server.api.OData;
|
||||||
|
|
||||||
|
public interface ODataFactory {
|
||||||
|
|
||||||
|
public OData newInstance();
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package org.baeldung.examples.olingo4;
|
||||||
|
|
||||||
|
import org.apache.olingo.server.api.ODataHttpHandler;
|
||||||
|
|
||||||
|
public interface ODataHttpHandlerFactory {
|
||||||
|
|
||||||
|
ODataHttpHandler newInstance();
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package org.baeldung.examples.olingo4;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider;
|
||||||
|
import org.apache.olingo.server.api.OData;
|
||||||
|
import org.apache.olingo.server.api.ODataHttpHandler;
|
||||||
|
import org.apache.olingo.server.api.ServiceMetadata;
|
||||||
|
import org.apache.olingo.server.api.processor.Processor;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
public class ODataHttpHandlerFactoryImpl implements ODataHttpHandlerFactory {
|
||||||
|
|
||||||
|
|
||||||
|
private final ODataFactory odataFactory;
|
||||||
|
private final CsdlEdmProvider edmProvider;
|
||||||
|
private final List<Processor> processors;
|
||||||
|
|
||||||
|
public ODataHttpHandlerFactoryImpl(ODataFactory odataFactory,CsdlEdmProvider edmProvider, List<Processor> processors) {
|
||||||
|
this.odataFactory = odataFactory;
|
||||||
|
this.edmProvider = edmProvider;
|
||||||
|
this.processors = processors;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ODataHttpHandler newInstance() {
|
||||||
|
|
||||||
|
OData odata = odataFactory.newInstance();
|
||||||
|
ServiceMetadata metadata = odata.createServiceMetadata(edmProvider, Collections.emptyList());
|
||||||
|
ODataHttpHandler handler = odata.createHandler(metadata);
|
||||||
|
|
||||||
|
// Register all available processors
|
||||||
|
processors.forEach(p -> handler.register(p));
|
||||||
|
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package org.baeldung.examples.olingo4;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
|
||||||
|
import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider;
|
||||||
|
import org.apache.olingo.server.api.processor.Processor;
|
||||||
|
import org.baeldung.examples.olingo4.ODataHttpHandlerFactoryImpl.ODataHttpHandlerFactoryImplBuilder;
|
||||||
|
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ODataHttpHandlerFactory httpHandlerFactory(CsdlEdmProvider edmProvider, ODataFactory odataFactory, List<Processor> processors) {
|
||||||
|
return new ODataHttpHandlerFactoryImplBuilder()
|
||||||
|
.edmProvider(edmProvider)
|
||||||
|
.odataFactory(odataFactory)
|
||||||
|
.processors(processors)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.baeldung.examples.olingo4;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
import javax.persistence.EntityTransaction;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.olingo.server.api.ODataHttpHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Philippe
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ODataServlet extends HttpServlet {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final ODataHttpHandlerFactory odataHttpHandlerFactory;
|
||||||
|
|
||||||
|
|
||||||
|
public ODataServlet(ODataHttpHandlerFactory factory, EntityManagerFactory emf) {
|
||||||
|
this.odataHttpHandlerFactory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
|
||||||
|
ODataHttpHandler handler = odataHttpHandlerFactory.newInstance();
|
||||||
|
handler.process(req, resp);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package org.baeldung.examples.olingo4;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Olingo4SampleApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Olingo4SampleApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package org.baeldung.examples.olingo4.domain;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
@Table(name="car_maker")
|
||||||
|
public class CarMaker {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy=GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name="name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy="maker",
|
||||||
|
orphanRemoval = true,
|
||||||
|
cascade=CascadeType.ALL)
|
||||||
|
private List<CarModel> models;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package org.baeldung.examples.olingo4.domain;
|
||||||
|
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
@Table(name="car_model")
|
||||||
|
public class CarModel {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy=GenerationType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Integer year;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String sku;
|
||||||
|
|
||||||
|
@ManyToOne(optional=false, fetch= FetchType.LAZY)
|
||||||
|
@JoinColumn(name="maker_fk")
|
||||||
|
private CarMaker maker;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package org.baeldung.examples.olingo4.edm;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.sql.Time;
|
||||||
|
import java.util.AbstractMap.SimpleEntry;
|
||||||
|
|
||||||
|
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class EdmTypeMapper {
|
||||||
|
|
||||||
|
public EdmPrimitiveTypeKind java2edm(Class<?> clazz) {
|
||||||
|
EdmPrimitiveTypeKind result = java2edm.get(clazz);
|
||||||
|
if ( result == null ) {
|
||||||
|
throw new IllegalArgumentException("[E19] Unsupported class mapping: class=" + clazz);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static map used generate attribute metadada based on Java types
|
||||||
|
static Map<Class<?>,EdmPrimitiveTypeKind> java2edm = Collections
|
||||||
|
.unmodifiableMap(Stream.of(
|
||||||
|
new SimpleEntry<>(Boolean.class,EdmPrimitiveTypeKind.Boolean),
|
||||||
|
new SimpleEntry<>(Byte.class,EdmPrimitiveTypeKind.SByte),
|
||||||
|
new SimpleEntry<>(Date.class,EdmPrimitiveTypeKind.Date),
|
||||||
|
new SimpleEntry<>(Time.class,EdmPrimitiveTypeKind.TimeOfDay),
|
||||||
|
new SimpleEntry<>(Number.class,EdmPrimitiveTypeKind.Decimal),
|
||||||
|
new SimpleEntry<>(Float.class,EdmPrimitiveTypeKind.Single),
|
||||||
|
new SimpleEntry<>(Double.class,EdmPrimitiveTypeKind.Double),
|
||||||
|
new SimpleEntry<>(UUID.class,EdmPrimitiveTypeKind.Guid),
|
||||||
|
new SimpleEntry<>(Short.class,EdmPrimitiveTypeKind.Int16),
|
||||||
|
new SimpleEntry<>(Integer.class,EdmPrimitiveTypeKind.Int32),
|
||||||
|
new SimpleEntry<>(Long.class,EdmPrimitiveTypeKind.Int64),
|
||||||
|
new SimpleEntry<>(String.class,EdmPrimitiveTypeKind.String)
|
||||||
|
|
||||||
|
).collect(Collectors.toMap((e)-> e.getKey(),(e)-> e.getValue())));
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,237 @@
|
|||||||
|
package org.baeldung.examples.olingo4.edm;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
import javax.persistence.metamodel.Attribute.PersistentAttributeType;
|
||||||
|
import javax.persistence.metamodel.EntityType;
|
||||||
|
import javax.persistence.metamodel.Metamodel;
|
||||||
|
import javax.persistence.metamodel.PluralAttribute;
|
||||||
|
import javax.persistence.metamodel.SingularAttribute;
|
||||||
|
|
||||||
|
import org.apache.olingo.commons.api.edm.FullQualifiedName;
|
||||||
|
import org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmProvider;
|
||||||
|
import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer;
|
||||||
|
import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainerInfo;
|
||||||
|
import org.apache.olingo.commons.api.edm.provider.CsdlEntitySet;
|
||||||
|
import org.apache.olingo.commons.api.edm.provider.CsdlEntityType;
|
||||||
|
import org.apache.olingo.commons.api.edm.provider.CsdlNavigationProperty;
|
||||||
|
import org.apache.olingo.commons.api.edm.provider.CsdlProperty;
|
||||||
|
import org.apache.olingo.commons.api.edm.provider.CsdlPropertyRef;
|
||||||
|
import org.apache.olingo.commons.api.edm.provider.CsdlSchema;
|
||||||
|
import org.apache.olingo.commons.api.ex.ODataException;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JpaEdmProvider extends CsdlAbstractEdmProvider {
|
||||||
|
|
||||||
|
EntityManagerFactory emf;
|
||||||
|
|
||||||
|
//
|
||||||
|
private EdmTypeMapper typeMapper;
|
||||||
|
|
||||||
|
// Service Namespace
|
||||||
|
public static final String NAMESPACE = "OData.Demo";
|
||||||
|
|
||||||
|
// EDM Container
|
||||||
|
public static final String CONTAINER_NAME = "Cars";
|
||||||
|
public static final FullQualifiedName CONTAINER = new FullQualifiedName(NAMESPACE, CONTAINER_NAME);
|
||||||
|
|
||||||
|
public JpaEdmProvider(EntityManagerFactory emf, EdmTypeMapper mapper) {
|
||||||
|
this.emf = emf;
|
||||||
|
this.typeMapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmProvider#getEntitySet(org.apache.olingo.commons.api.edm.FullQualifiedName, java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) throws ODataException {
|
||||||
|
|
||||||
|
if (entityContainer.equals(CONTAINER)) {
|
||||||
|
|
||||||
|
EntityType<?> e = emf.getMetamodel()
|
||||||
|
.getEntities()
|
||||||
|
.stream()
|
||||||
|
.filter((ent) -> (ent.getName() + "s")
|
||||||
|
.equals(entitySetName))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (e != null) {
|
||||||
|
CsdlEntitySet entitySet = new CsdlEntitySet();
|
||||||
|
entitySet.setName(entitySetName);
|
||||||
|
entitySet.setType(new FullQualifiedName(NAMESPACE, e.getName()));
|
||||||
|
return entitySet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmProvider#getEntityContainerInfo(org.apache.olingo.commons.api.edm.FullQualifiedName)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) throws ODataException {
|
||||||
|
|
||||||
|
// This method is invoked when displaying the Service Document at e.g. http://localhost:8080/DemoService/DemoService.svc
|
||||||
|
if (entityContainerName == null || entityContainerName.equals(CONTAINER)) {
|
||||||
|
CsdlEntityContainerInfo entityContainerInfo = new CsdlEntityContainerInfo();
|
||||||
|
entityContainerInfo.setContainerName(CONTAINER);
|
||||||
|
return entityContainerInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmProvider#getSchemas()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<CsdlSchema> getSchemas() throws ODataException {
|
||||||
|
// create Schema
|
||||||
|
CsdlSchema schema = new CsdlSchema();
|
||||||
|
schema.setNamespace(NAMESPACE);
|
||||||
|
|
||||||
|
// add EntityTypes
|
||||||
|
List<CsdlEntityType> entityTypes = emf.getMetamodel()
|
||||||
|
.getEntities()
|
||||||
|
.stream()
|
||||||
|
.map((e) -> {
|
||||||
|
try {
|
||||||
|
return getEntityType(new FullQualifiedName(NAMESPACE, e.getName()));
|
||||||
|
} catch (ODataException oe) {
|
||||||
|
throw new RuntimeException(oe);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
schema.setEntityTypes(entityTypes);
|
||||||
|
|
||||||
|
// add EntityContainer
|
||||||
|
schema.setEntityContainer(getEntityContainer());
|
||||||
|
|
||||||
|
// finally
|
||||||
|
List<CsdlSchema> schemas = new ArrayList<CsdlSchema>();
|
||||||
|
schemas.add(schema);
|
||||||
|
|
||||||
|
return schemas;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmProvider#getEntityContainer()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CsdlEntityContainer getEntityContainer() throws ODataException {
|
||||||
|
|
||||||
|
|
||||||
|
// add EntityTypes
|
||||||
|
List<CsdlEntitySet> entitySets = emf.getMetamodel()
|
||||||
|
.getEntities()
|
||||||
|
.stream()
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// create EntityContainer
|
||||||
|
CsdlEntityContainer entityContainer = new CsdlEntityContainer();
|
||||||
|
entityContainer.setName(CONTAINER_NAME);
|
||||||
|
entityContainer.setEntitySets(entitySets);
|
||||||
|
|
||||||
|
return entityContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) throws ODataException {
|
||||||
|
|
||||||
|
Metamodel mm = emf.getMetamodel();
|
||||||
|
|
||||||
|
CsdlEntityType result = null;
|
||||||
|
|
||||||
|
result = mm.getEntities()
|
||||||
|
.stream()
|
||||||
|
.filter(et -> entityTypeName.equals(new FullQualifiedName(NAMESPACE, et.getName())))
|
||||||
|
.map(et -> buildODataType(et))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps a JPA type to its OData counterpart.
|
||||||
|
* @param et
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected CsdlEntityType buildODataType(EntityType<?> et) {
|
||||||
|
|
||||||
|
CsdlEntityType result = new CsdlEntityType();
|
||||||
|
result.setName(et.getName());
|
||||||
|
|
||||||
|
// Process simple properties
|
||||||
|
List<CsdlProperty> properties = et.getDeclaredSingularAttributes()
|
||||||
|
.stream()
|
||||||
|
.filter(attr -> attr.getPersistentAttributeType() == PersistentAttributeType.BASIC)
|
||||||
|
.map(attr -> buildBasicAttribute(et, attr))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
result.setProperties(properties);
|
||||||
|
|
||||||
|
// Process Ids
|
||||||
|
List<CsdlPropertyRef> ids = et.getDeclaredSingularAttributes()
|
||||||
|
.stream()
|
||||||
|
.filter(attr -> attr.getPersistentAttributeType() == PersistentAttributeType.BASIC && attr.isId())
|
||||||
|
.map(attr -> buildRefAttribute(et, attr))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
result.setKey(ids);
|
||||||
|
|
||||||
|
// Process navs
|
||||||
|
List<CsdlNavigationProperty> navs = et.getDeclaredPluralAttributes()
|
||||||
|
.stream()
|
||||||
|
.map(attr -> buildNavAttribute(et, attr))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
result.setNavigationProperties(navs);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CsdlProperty buildBasicAttribute(EntityType<?> et, SingularAttribute<?, ?> attr) {
|
||||||
|
|
||||||
|
CsdlProperty p = new CsdlProperty().setName(attr.getName())
|
||||||
|
.setType(typeMapper.java2edm(attr.getJavaType())
|
||||||
|
.getFullQualifiedName())
|
||||||
|
.setNullable(et.getDeclaredSingularAttribute(attr.getName())
|
||||||
|
.isOptional());
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CsdlPropertyRef buildRefAttribute(EntityType<?> et, SingularAttribute<?, ?> attr) {
|
||||||
|
|
||||||
|
CsdlPropertyRef p = new CsdlPropertyRef().setName(attr.getName());
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,185 @@
|
|||||||
|
package org.baeldung.examples.olingo4.processor;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
import javax.persistence.metamodel.EntityType;
|
||||||
|
import javax.persistence.metamodel.SingularAttribute;
|
||||||
|
|
||||||
|
import org.apache.commons.beanutils.PropertyUtils;
|
||||||
|
import org.apache.olingo.commons.api.data.ContextURL;
|
||||||
|
import org.apache.olingo.commons.api.data.Entity;
|
||||||
|
import org.apache.olingo.commons.api.data.EntityCollection;
|
||||||
|
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.edm.EdmEntityType;
|
||||||
|
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
|
||||||
|
import org.apache.olingo.commons.api.format.ContentType;
|
||||||
|
import org.apache.olingo.commons.api.http.HttpHeader;
|
||||||
|
import org.apache.olingo.commons.api.http.HttpStatusCode;
|
||||||
|
import org.apache.olingo.server.api.OData;
|
||||||
|
import org.apache.olingo.server.api.ODataApplicationException;
|
||||||
|
import org.apache.olingo.server.api.ODataLibraryException;
|
||||||
|
import org.apache.olingo.server.api.ODataRequest;
|
||||||
|
import org.apache.olingo.server.api.ODataResponse;
|
||||||
|
import org.apache.olingo.server.api.ServiceMetadata;
|
||||||
|
import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor;
|
||||||
|
import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
|
||||||
|
import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions;
|
||||||
|
import org.apache.olingo.server.api.serializer.ODataSerializer;
|
||||||
|
import org.apache.olingo.server.api.serializer.SerializerResult;
|
||||||
|
import org.apache.olingo.server.api.uri.UriInfo;
|
||||||
|
import org.apache.olingo.server.api.uri.UriResource;
|
||||||
|
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
|
||||||
|
import org.baeldung.examples.olingo4.repository.RepositoryRegistry;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JpaEntityCollectionProcessor implements CountEntityCollectionProcessor {
|
||||||
|
|
||||||
|
private OData odata;
|
||||||
|
private ServiceMetadata serviceMetadata;
|
||||||
|
private EntityManagerFactory emf;
|
||||||
|
private RepositoryRegistry repositoryRegistry;
|
||||||
|
|
||||||
|
public JpaEntityCollectionProcessor(EntityManagerFactory emf, RepositoryRegistry repositoryRegistry) {
|
||||||
|
this.emf = emf;
|
||||||
|
this.repositoryRegistry = repositoryRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(OData odata, ServiceMetadata serviceMetadata) {
|
||||||
|
this.odata = odata;
|
||||||
|
this.serviceMetadata = serviceMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat) throws ODataApplicationException, ODataLibraryException {
|
||||||
|
|
||||||
|
// 1st we have retrieve the requested EntitySet from the uriInfo object (representation of the parsed service URI)
|
||||||
|
List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
|
||||||
|
UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0); // in our example, the first segment is the EntitySet
|
||||||
|
EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet();
|
||||||
|
|
||||||
|
// 2nd: fetch the data from backend for this requested EntitySetName
|
||||||
|
// it has to be delivered as EntitySet object
|
||||||
|
EntityCollection entitySet = getData(edmEntitySet, uriInfo);
|
||||||
|
|
||||||
|
// 3rd: create a serializer based on the requested format (json)
|
||||||
|
ODataSerializer serializer = odata.createSerializer(responseFormat);
|
||||||
|
|
||||||
|
// 4th: Now serialize the content: transform from the EntitySet object to InputStream
|
||||||
|
EdmEntityType edmEntityType = edmEntitySet.getEntityType();
|
||||||
|
ContextURL contextUrl = ContextURL.with()
|
||||||
|
.entitySet(edmEntitySet)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final String id = request.getRawBaseUri() + "/" + edmEntitySet.getName();
|
||||||
|
EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with()
|
||||||
|
.id(id)
|
||||||
|
.contextURL(contextUrl)
|
||||||
|
.build();
|
||||||
|
SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, edmEntityType, entitySet, opts);
|
||||||
|
InputStream serializedContent = serializerResult.getContent();
|
||||||
|
|
||||||
|
// Finally: configure the response object: set the body, headers and status code
|
||||||
|
response.setContent(serializedContent);
|
||||||
|
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
|
||||||
|
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void countEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo) throws ODataApplicationException, ODataLibraryException {
|
||||||
|
|
||||||
|
// 1st we have retrieve the requested EntitySet from the uriInfo object (representation of the parsed service URI)
|
||||||
|
List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
|
||||||
|
UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0); // in our example, the first segment is the EntitySet
|
||||||
|
EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet();
|
||||||
|
|
||||||
|
// 2nd: fetch the data from backend for this requested EntitySetName
|
||||||
|
Long count = getCount(edmEntitySet, uriInfo);
|
||||||
|
|
||||||
|
// Finally: configure the response object: set the body, headers and status code
|
||||||
|
response.setContent(new ByteArrayInputStream(count.toString()
|
||||||
|
.getBytes()));
|
||||||
|
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
|
||||||
|
response.setHeader(HttpHeader.CONTENT_TYPE, "text/plain");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private EntityCollection getData(EdmEntitySet edmEntitySet, UriInfo uriInfo) {
|
||||||
|
|
||||||
|
EdmEntityType type = edmEntitySet.getEntityType();
|
||||||
|
JpaRepository<?, ?> repo = repositoryRegistry.getRepositoryForEntity(type);
|
||||||
|
EntityCollection result = new EntityCollection();
|
||||||
|
|
||||||
|
repo.findAll()
|
||||||
|
.stream()
|
||||||
|
.forEach((it) -> result.getEntities()
|
||||||
|
.add(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long getCount(EdmEntitySet edmEntitySet, UriInfo uriInfo) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package org.baeldung.examples.olingo4.repository;
|
||||||
|
|
||||||
|
import org.baeldung.examples.olingo4.domain.CarMaker;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface CarMakerRepository extends JpaRepository<CarMaker, Long>, JpaSpecificationExecutor<CarMaker>, EdmEntityRepository {
|
||||||
|
|
||||||
|
public default String getEdmEntityName() { return CarMaker.class.getSimpleName();}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package org.baeldung.examples.olingo4.repository;
|
||||||
|
|
||||||
|
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 default String getEdmEntityName() { return CarModel.class.getSimpleName();}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.baeldung.examples.olingo4.repository;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Philippe
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface EdmEntityRepository {
|
||||||
|
|
||||||
|
public String getEdmEntityName();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package org.baeldung.examples.olingo4.repository;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
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<>();
|
||||||
|
|
||||||
|
public RepositoryRegistry(List<EdmEntityRepository> allRepositories) {
|
||||||
|
|
||||||
|
allRepositories.stream().forEach((r) ->
|
||||||
|
repositoriesByClassName.put(r.getEdmEntityName(),(JpaRepository<?,?>)r));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public JpaRepository<?, ?> getRepositoryForEntity(EdmEntityType entityType) {
|
||||||
|
JpaRepository<?, ?> repo = repositoriesByClassName.get(entityType.getName());
|
||||||
|
return repo;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
spring:
|
||||||
|
jpa:
|
||||||
|
show-sql: true
|
||||||
|
open-in-view: false
|
||||||
|
hibernate:
|
||||||
|
ddl-auto: update
|
12
apache-olingo/olingo4/src/main/resources/data.sql
Normal file
12
apache-olingo/olingo4/src/main/resources/data.sql
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
insert into car_maker(id,name) values (1,'Special Motors');
|
||||||
|
insert into car_maker(id,name) values (2,'BWM');
|
||||||
|
insert into car_maker(id,name) values (3,'Dolores');
|
||||||
|
|
||||||
|
insert into car_model(id,maker_fk,name,sku,year) values(1,1,'Muze','SM001',2018);
|
||||||
|
insert into car_model(id,maker_fk,name,sku,year) values(2,1,'Empada','SM002',2008);
|
||||||
|
|
||||||
|
insert into car_model(id,maker_fk,name,sku,year) values(4,2,'BWM-100','BWM100',2008);
|
||||||
|
insert into car_model(id,maker_fk,name,sku,year) values(5,2,'BWM-200','BWM200',2009);
|
||||||
|
insert into car_model(id,maker_fk,name,sku,year) values(6,2,'BWM-300','BWM300',2008);
|
||||||
|
|
||||||
|
alter sequence hibernate_sequence restart with 100;
|
@ -0,0 +1,16 @@
|
|||||||
|
package org.baeldung.examples.olingo4;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest
|
||||||
|
public class Olingo4SampleApplicationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void contextLoads() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user