diff --git a/linkrest/WebContent/META-INF/MANIFEST.MF b/linkrest/WebContent/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..254272e1c0
--- /dev/null
+++ b/linkrest/WebContent/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path:
+
diff --git a/linkrest/WebContent/WEB-INF/web.xml b/linkrest/WebContent/WEB-INF/web.xml
new file mode 100644
index 0000000000..046c82b08a
--- /dev/null
+++ b/linkrest/WebContent/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+ linkrest
+
+ linkrest
+ org.glassfish.jersey.servlet.ServletContainer
+
+ javax.ws.rs.Application
+ com.baeldung.LinkRestApplication
+
+ 1
+
+
+ linkrest
+ /*
+
+
\ No newline at end of file
diff --git a/linkrest/pom.xml b/linkrest/pom.xml
new file mode 100644
index 0000000000..aa2f0f8bda
--- /dev/null
+++ b/linkrest/pom.xml
@@ -0,0 +1,81 @@
+
+ 4.0.0
+ com.baeldung
+ linkrest
+ 0.0.1-SNAPSHOT
+ war
+
+
+
+ com.nhl.link.rest
+ link-rest
+ ${linkrest.version}
+
+
+ org.glassfish.jersey.containers
+ jersey-container-servlet
+ ${jersey.version}
+
+
+ org.glassfish.jersey.media
+ jersey-media-moxy
+ ${jersey.version}
+
+
+ com.h2database
+ h2
+ ${h2.version}
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.5
+
+ 1.8
+ 1.8
+
+
+
+ maven-war-plugin
+ 2.6
+
+ WebContent
+ false
+
+
+
+ org.apache.cayenne.plugins
+ cayenne-maven-plugin
+ ${cayenne.version}
+
+
+
+
+
+
+
+
+ cgen
+
+
+
+
+
+ org.apache.cayenne.plugins
+ cayenne-modeler-maven-plugin
+ ${cayenne.version}
+
+
+
+
+
+ 2.9
+ 4.0.B1
+ 1.4.196
+ 2.25.1
+
+
\ No newline at end of file
diff --git a/linkrest/src/main/java/com/baeldung/LinkRestApplication.java b/linkrest/src/main/java/com/baeldung/LinkRestApplication.java
new file mode 100644
index 0000000000..7a2f7c8903
--- /dev/null
+++ b/linkrest/src/main/java/com/baeldung/LinkRestApplication.java
@@ -0,0 +1,24 @@
+package com.baeldung;
+
+
+import javax.ws.rs.ApplicationPath;
+
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import com.nhl.link.rest.runtime.LinkRestBuilder;
+import com.nhl.link.rest.runtime.LinkRestRuntime;
+
+@ApplicationPath("/linkrest")
+public class LinkRestApplication extends ResourceConfig {
+
+ public LinkRestApplication() {
+ ServerRuntime cayenneRuntime = ServerRuntime.builder()
+ .addConfig("cayenne-linkrest-project.xml")
+ .build();
+ LinkRestRuntime lrRuntime = LinkRestBuilder.build(cayenneRuntime);
+ super.register(lrRuntime);
+ packages("com.baeldung.linkrest.apis");
+ }
+
+}
diff --git a/linkrest/src/main/java/com/baeldung/cayenne/Department.java b/linkrest/src/main/java/com/baeldung/cayenne/Department.java
new file mode 100644
index 0000000000..ed7a2bd795
--- /dev/null
+++ b/linkrest/src/main/java/com/baeldung/cayenne/Department.java
@@ -0,0 +1,9 @@
+package com.baeldung.cayenne;
+
+import com.baeldung.cayenne.auto._Department;
+
+public class Department extends _Department {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/linkrest/src/main/java/com/baeldung/cayenne/Employee.java b/linkrest/src/main/java/com/baeldung/cayenne/Employee.java
new file mode 100644
index 0000000000..632ea4fbf9
--- /dev/null
+++ b/linkrest/src/main/java/com/baeldung/cayenne/Employee.java
@@ -0,0 +1,9 @@
+package com.baeldung.cayenne;
+
+import com.baeldung.cayenne.auto._Employee;
+
+public class Employee extends _Employee {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/linkrest/src/main/java/com/baeldung/cayenne/auto/_Department.java b/linkrest/src/main/java/com/baeldung/cayenne/auto/_Department.java
new file mode 100644
index 0000000000..4111a8c8b2
--- /dev/null
+++ b/linkrest/src/main/java/com/baeldung/cayenne/auto/_Department.java
@@ -0,0 +1,44 @@
+package com.baeldung.cayenne.auto;
+
+import java.util.List;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.exp.Property;
+
+import com.baeldung.cayenne.Employee;
+
+/**
+ * Class _Department was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _Department extends CayenneDataObject {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final String DEP_ID_PK_COLUMN = "dep_id";
+
+ public static final Property NAME = Property.create("name", String.class);
+ public static final Property> EMPLOYEES = Property.create("employees", List.class);
+
+ public void setName(String name) {
+ writeProperty("name", name);
+ }
+ public String getName() {
+ return (String)readProperty("name");
+ }
+
+ public void addToEmployees(Employee obj) {
+ addToManyTarget("employees", obj, true);
+ }
+ public void removeFromEmployees(Employee obj) {
+ removeToManyTarget("employees", obj, true);
+ }
+ @SuppressWarnings("unchecked")
+ public List getEmployees() {
+ return (List)readProperty("employees");
+ }
+
+
+}
diff --git a/linkrest/src/main/java/com/baeldung/cayenne/auto/_Employee.java b/linkrest/src/main/java/com/baeldung/cayenne/auto/_Employee.java
new file mode 100644
index 0000000000..50e1880a56
--- /dev/null
+++ b/linkrest/src/main/java/com/baeldung/cayenne/auto/_Employee.java
@@ -0,0 +1,39 @@
+package com.baeldung.cayenne.auto;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.exp.Property;
+
+import com.baeldung.cayenne.Department;
+
+/**
+ * Class _Employee was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _Employee extends CayenneDataObject {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final String EMP_ID_PK_COLUMN = "emp_id";
+
+ public static final Property NAME = Property.create("name", String.class);
+ public static final Property DEPARTMENT = Property.create("department", Department.class);
+
+ public void setName(String name) {
+ writeProperty("name", name);
+ }
+ public String getName() {
+ return (String)readProperty("name");
+ }
+
+ public void setDepartment(Department department) {
+ setToOneTarget("department", department, true);
+ }
+
+ public Department getDepartment() {
+ return (Department)readProperty("department");
+ }
+
+
+}
diff --git a/linkrest/src/main/java/com/baeldung/linkrest/apis/DepartmentResource.java b/linkrest/src/main/java/com/baeldung/linkrest/apis/DepartmentResource.java
new file mode 100644
index 0000000000..f4090b580e
--- /dev/null
+++ b/linkrest/src/main/java/com/baeldung/linkrest/apis/DepartmentResource.java
@@ -0,0 +1,58 @@
+package com.baeldung.linkrest.apis;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+
+import com.baeldung.cayenne.Department;
+import com.nhl.link.rest.DataResponse;
+import com.nhl.link.rest.LinkRest;
+import com.nhl.link.rest.SimpleResponse;
+
+@Path("department")
+@Produces(MediaType.APPLICATION_JSON)
+public class DepartmentResource {
+
+ @Context
+ private Configuration config;
+
+ @GET
+ public DataResponse getAll(@Context UriInfo uriInfo) {
+ return LinkRest.select(Department.class, config).uri(uriInfo).get();
+ }
+
+ @GET
+ @Path("{id}")
+ public DataResponse getOne(@PathParam("id") int id, @Context UriInfo uriInfo) {
+ return LinkRest.select(Department.class, config).byId(id).uri(uriInfo).getOne();
+ }
+
+ @POST
+ public SimpleResponse create(String data) {
+ return LinkRest.create(Department.class, config).sync(data);
+ }
+
+ @PUT
+ public SimpleResponse createOrUpdate(String data) {
+ return LinkRest.createOrUpdate(Department.class, config).sync(data);
+ }
+
+ @Path("{id}/employees")
+ public EmployeeSubResource getEmployees(@PathParam("id") int id, @Context UriInfo uriInfo) {
+ return new EmployeeSubResource(id, config);
+ }
+
+ @DELETE
+ @Path("{id}")
+ public SimpleResponse delete(@PathParam("id") int id) {
+ return LinkRest.delete(Department.class, config).id(id).delete();
+ }
+}
diff --git a/linkrest/src/main/java/com/baeldung/linkrest/apis/EmployeeSubResource.java b/linkrest/src/main/java/com/baeldung/linkrest/apis/EmployeeSubResource.java
new file mode 100644
index 0000000000..ba9c3759bb
--- /dev/null
+++ b/linkrest/src/main/java/com/baeldung/linkrest/apis/EmployeeSubResource.java
@@ -0,0 +1,65 @@
+package com.baeldung.linkrest.apis;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+
+import com.baeldung.cayenne.Department;
+import com.baeldung.cayenne.Employee;
+import com.nhl.link.rest.DataResponse;
+import com.nhl.link.rest.LinkRest;
+import com.nhl.link.rest.SimpleResponse;
+
+@Produces(MediaType.APPLICATION_JSON)
+public class EmployeeSubResource {
+
+ private Configuration config;
+
+ private int departmentId;
+
+ public EmployeeSubResource(int departmentId, Configuration config) {
+ this.departmentId = departmentId;
+ this.config = config;
+ }
+
+ public EmployeeSubResource() {
+ }
+
+ @GET
+ public DataResponse getAll(@Context UriInfo uriInfo) {
+ return LinkRest.select(Employee.class, config).toManyParent(Department.class, departmentId, Department.EMPLOYEES).uri(uriInfo).get();
+ }
+
+ @GET
+ @Path("{id}")
+ public DataResponse getOne(@PathParam("id") int id, @Context UriInfo uriInfo) {
+ return LinkRest.select(Employee.class, config).toManyParent(Department.class, departmentId, Department.EMPLOYEES).byId(id).uri(uriInfo).getOne();
+ }
+
+ @POST
+ public SimpleResponse create(String data) {
+
+ return LinkRest.create(Employee.class, config).toManyParent(Department.class, departmentId, Department.EMPLOYEES).sync(data);
+ }
+
+ @PUT
+ public SimpleResponse createOrUpdate(String data) {
+ return LinkRest.create(Employee.class, config).toManyParent(Department.class, departmentId, Department.EMPLOYEES).sync(data);
+ }
+
+ @DELETE
+ @Path("{id}")
+ public SimpleResponse delete(@PathParam("id") int id) {
+ return LinkRest.delete(Employee.class, config).toManyParent(Department.class, departmentId, Department.EMPLOYEES).id(id).delete();
+
+ }
+
+}
diff --git a/linkrest/src/main/resources/cayenne-linkrest-project.xml b/linkrest/src/main/resources/cayenne-linkrest-project.xml
new file mode 100644
index 0000000000..8a4ba39c4d
--- /dev/null
+++ b/linkrest/src/main/resources/cayenne-linkrest-project.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/linkrest/src/main/resources/linkrest.map.xml b/linkrest/src/main/resources/linkrest.map.xml
new file mode 100644
index 0000000000..105d7d9d14
--- /dev/null
+++ b/linkrest/src/main/resources/linkrest.map.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index fac746f7df..015efbab05 100644
--- a/pom.xml
+++ b/pom.xml
@@ -97,7 +97,8 @@
jws
libraries
- libraries-data
+ libraries-data
+ linkrest
log-mdc
log4j
log4j2