From e223459db81c4c03e741450b65171647d2584798 Mon Sep 17 00:00:00 2001 From: Chak-C <114961815+Chak-C@users.noreply.github.com> Date: Thu, 29 Dec 2022 20:17:28 +1100 Subject: [PATCH] feature: Add context object pattern (#2304) * Add context object pattern and corresponding tests * Update context pattern * Add README, class diagram, puml file. Add toString method in ServiceContext.java. Add tests for coverage. * Improvements: Remove plugin in pom file Add comments in app.java Change local variable keyword to var in app.java Use lombok for getters, setters and tostring Change method signature in context object * Refreshing environment-1 * Reconfigure pom file. Co-authored-by: Alvis Chan Co-authored-by: u7287079 --- context-object/README.md | 184 ++++++++++++++++++ context-object/etc/context-object.png | Bin 0 -> 67111 bytes context-object/etc/context-object.urm.puml | 50 +++++ context-object/pom.xml | 62 ++++++ .../java/com/iluwatar/context/object/App.java | 41 ++++ .../com/iluwatar/context/object/LayerA.java | 17 ++ .../com/iluwatar/context/object/LayerB.java | 17 ++ .../com/iluwatar/context/object/LayerC.java | 17 ++ .../context/object/ServiceContext.java | 16 ++ .../context/object/ServiceContextFactory.java | 11 ++ .../com/iluwatar/contect/object/AppTest.java | 17 ++ .../contect/object/ServiceContextTest.java | 66 +++++++ 12 files changed, 498 insertions(+) create mode 100644 context-object/README.md create mode 100644 context-object/etc/context-object.png create mode 100644 context-object/etc/context-object.urm.puml create mode 100644 context-object/pom.xml create mode 100644 context-object/src/main/java/com/iluwatar/context/object/App.java create mode 100644 context-object/src/main/java/com/iluwatar/context/object/LayerA.java create mode 100644 context-object/src/main/java/com/iluwatar/context/object/LayerB.java create mode 100644 context-object/src/main/java/com/iluwatar/context/object/LayerC.java create mode 100644 context-object/src/main/java/com/iluwatar/context/object/ServiceContext.java create mode 100644 context-object/src/main/java/com/iluwatar/context/object/ServiceContextFactory.java create mode 100644 context-object/src/test/java/com/iluwatar/contect/object/AppTest.java create mode 100644 context-object/src/test/java/com/iluwatar/contect/object/ServiceContextTest.java diff --git a/context-object/README.md b/context-object/README.md new file mode 100644 index 000000000..0c4462aa6 --- /dev/null +++ b/context-object/README.md @@ -0,0 +1,184 @@ +--- +title: Context object +category: Creational +language: en +tags: +- Data access +--- + +## Name / classification + +Context Object + +## Also known as + +Context, Encapsulate Context + +## Intent + +Decouple data from protocol-specific classes and store the scoped data in an object independent +of the underlying protocol technology. + +## Explanation + +Real-world example + +> This application has different layers labelled A, B and C with each extracting specific information +> from a similar context for further use in the software. Passing down each pieces of information +> individually would be inefficient, a method to efficiently store and pass information is needed. + +In plain words + +> Create an object and store the data there and pass this object to where it is needed. + +[Core J2EE Patterns](http://corej2eepatterns.com/ContextObject.htm) says + +> Use a Context Object to encapsulate state in a protocol-independent way to be shared throughout your application. + +**Programmatic Example** + +We define what data a service context object contains. + +```Java +public class ServiceContext { + + String ACCOUNT_SERVICE, SESSION_SERVICE, SEARCH_SERVICE; + + public void setACCOUNT_SERVICE(String ACCOUNT_SERVICE) { + this.ACCOUNT_SERVICE = ACCOUNT_SERVICE; + } + + public void setSESSION_SERVICE(String SESSION_SERVICE) { + this.SESSION_SERVICE = SESSION_SERVICE; + } + + public void setSEARCH_SERVICE(String SEARCH_SERVICE) { + this.SEARCH_SERVICE = SEARCH_SERVICE; + } + + public String getACCOUNT_SERVICE() { + return ACCOUNT_SERVICE; + } + + public String getSESSION_SERVICE() { + return SESSION_SERVICE; + } + + public String getSEARCH_SERVICE() { + return SEARCH_SERVICE; + } + + public String toString() { return ACCOUNT_SERVICE + " " + SESSION_SERVICE + " " + SEARCH_SERVICE;} +} +``` + +Create an interface used in parts of the application for context objects to be created. + +```Java +public class ServiceContextFactory { + + public static ServiceContext createContext() { + return new ServiceContext(); + } +} +``` + +Instantiate the context object in the first layer and the adjoining layer upcalls the context in the current layer, which +then further structures the object. + +```Java +public class LayerA { + + private static ServiceContext context; + + public LayerA() { + context = ServiceContextFactory.createContext(); + } + + public static ServiceContext getContext() { + return context; + } + + public void addAccountInfo(String accountService) { + context.setACCOUNT_SERVICE(accountService); + } +} + +public class LayerB { + + private static ServiceContext context; + + public LayerB(LayerA layerA) { + this.context = layerA.getContext(); + } + + public static ServiceContext getContext() { + return context; + } + + public void addSessionInfo(String sessionService) { + context.setSESSION_SERVICE(sessionService); + } +} + +public class LayerC { + + public static ServiceContext context; + + public LayerC(LayerB layerB) { + this.context = layerB.getContext(); + } + + public static ServiceContext getContext() { + return context; + } + + public void addSearchInfo(String searchService) { + context.setSEARCH_SERVICE(searchService); + } +} +``` +Here is the context object and layers in action. + +```Java +var layerA = new LayerA(); +layerA.addAccountInfo(SERVICE); +LOGGER.info("Context = {}",layerA.getContext()); +var layerB = new LayerB(layerA); +layerB.addSessionInfo(SERVICE); +LOGGER.info("Context = {}",layerB.getContext()); +var layerC = new LayerC(layerB); +layerC.addSearchInfo(SERVICE); +LOGGER.info("Context = {}",layerC.getContext()); +``` + +Program output: + +```Java +Context = SERVICE null null +Context = SERVICE SERVICE null +Context = SERVICE SERVICE SERVICE +``` + +## Class diagram + +![alt text](./etc/context-object.png "Context object") + +## Application + +Use the Context Object pattern for: + +* Sharing information across different system layers. +* Decoupling software data from protocol-specific contexts. +* Exposing only the relevant API's within the context. + +## Known uses +* [Spring: ApplicationContext](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html) +* [Oracle: SecurityContext](https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/SecurityContext.html) +* [Oracle: ServletContext](https://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html) + +## Credits + +* [J2EE Design Patterns](http://corej2eepatterns.com/ContextObject.htm) +* [Allan Kelly - The Encapsulate Context Pattern](https://accu.org/journals/overload/12/63/kelly_246/) +* [Arvid S. Krishna et al. - Context Object](https://www.dre.vanderbilt.edu/~schmidt/PDF/Context-Object-Pattern.pdf) \ No newline at end of file diff --git a/context-object/etc/context-object.png b/context-object/etc/context-object.png new file mode 100644 index 0000000000000000000000000000000000000000..a1f670812f7ba27e600532ba541b19222df81271 GIT binary patch literal 67111 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 PBjFPfCKb1e64cKC LayerB +ServiceContext --> LayerC +ServiceContext --> LayerB +ServiceContext --> LayerA +ServiceContextFactory ..|> "<>" ServiceContext +LayerB ..|> LayerA +@enduml \ No newline at end of file diff --git a/context-object/pom.xml b/context-object/pom.xml new file mode 100644 index 000000000..4eb0237a6 --- /dev/null +++ b/context-object/pom.xml @@ -0,0 +1,62 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + context-object + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.compositeview.App + + + + + + + + + \ No newline at end of file diff --git a/context-object/src/main/java/com/iluwatar/context/object/App.java b/context-object/src/main/java/com/iluwatar/context/object/App.java new file mode 100644 index 000000000..c76ddd93b --- /dev/null +++ b/context-object/src/main/java/com/iluwatar/context/object/App.java @@ -0,0 +1,41 @@ +package com.iluwatar.context.object; + +import lombok.extern.slf4j.Slf4j; + +/** + * In the context object pattern, information and data from underlying protocol-specific classes/systems is decoupled + * and stored into a protocol-independent object in an organised format. The pattern ensures the data contained within + * the context object can be shared and further structured between different layers of a software system. + * + *

In this example we show how a context object {@link ServiceContext} can be initiated, edited and passed/retrieved + * in different layers of the program ({@link LayerA}, {@link LayerB}, {@link LayerC}) through use of static methods.

+ */ +@Slf4j +public class App { + + private static final String SERVICE = "SERVICE"; + + /** + * Program entry point. + * @param args command line args + */ + public static void main(String[] args) { + //Initiate first layer and add service information into context + var layerA = new LayerA(); + layerA.addAccountInfo(SERVICE); + + LOGGER.info("Context = {}",layerA.getContext()); + + //Initiate second layer and preserving information retrieved in first layer through passing context object + var layerB = new LayerB(layerA); + layerB.addSessionInfo(SERVICE); + + LOGGER.info("Context = {}",layerB.getContext()); + + //Initiate third layer and preserving information retrieved in first and second layer through passing context object + var layerC = new LayerC(layerB); + layerC.addSearchInfo(SERVICE); + + LOGGER.info("Context = {}",layerC.getContext()); + } +} diff --git a/context-object/src/main/java/com/iluwatar/context/object/LayerA.java b/context-object/src/main/java/com/iluwatar/context/object/LayerA.java new file mode 100644 index 000000000..f7a634448 --- /dev/null +++ b/context-object/src/main/java/com/iluwatar/context/object/LayerA.java @@ -0,0 +1,17 @@ +package com.iluwatar.context.object; + +import lombok.Getter; + +@Getter +public class LayerA { + + private ServiceContext context; + + public LayerA() { + context = ServiceContextFactory.createContext(); + } + + public void addAccountInfo(String accountService) { + context.setAccountService(accountService); + } +} diff --git a/context-object/src/main/java/com/iluwatar/context/object/LayerB.java b/context-object/src/main/java/com/iluwatar/context/object/LayerB.java new file mode 100644 index 000000000..8e4bd9c0f --- /dev/null +++ b/context-object/src/main/java/com/iluwatar/context/object/LayerB.java @@ -0,0 +1,17 @@ +package com.iluwatar.context.object; + +import lombok.Getter; + +@Getter +public class LayerB { + + private ServiceContext context; + + public LayerB(LayerA layerA) { + this.context = layerA.getContext(); + } + + public void addSessionInfo(String sessionService) { + context.setSessionService(sessionService); + } +} diff --git a/context-object/src/main/java/com/iluwatar/context/object/LayerC.java b/context-object/src/main/java/com/iluwatar/context/object/LayerC.java new file mode 100644 index 000000000..b6a23b539 --- /dev/null +++ b/context-object/src/main/java/com/iluwatar/context/object/LayerC.java @@ -0,0 +1,17 @@ +package com.iluwatar.context.object; + +import lombok.Getter; + +@Getter +public class LayerC { + + public ServiceContext context; + + public LayerC(LayerB layerB) { + this.context = layerB.getContext(); + } + + public void addSearchInfo(String searchService) { + context.setSearchService(searchService); + } +} diff --git a/context-object/src/main/java/com/iluwatar/context/object/ServiceContext.java b/context-object/src/main/java/com/iluwatar/context/object/ServiceContext.java new file mode 100644 index 000000000..9f334d374 --- /dev/null +++ b/context-object/src/main/java/com/iluwatar/context/object/ServiceContext.java @@ -0,0 +1,16 @@ +package com.iluwatar.context.object; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** + * Where context objects are defined. + */ +@ToString +@Getter +@Setter +public class ServiceContext { + + String AccountService, SessionService, SearchService; +} diff --git a/context-object/src/main/java/com/iluwatar/context/object/ServiceContextFactory.java b/context-object/src/main/java/com/iluwatar/context/object/ServiceContextFactory.java new file mode 100644 index 000000000..d3fe442df --- /dev/null +++ b/context-object/src/main/java/com/iluwatar/context/object/ServiceContextFactory.java @@ -0,0 +1,11 @@ +package com.iluwatar.context.object; + +/** + * An interface to create context objects passed through layers. + */ +public class ServiceContextFactory { + + public static ServiceContext createContext() { + return new ServiceContext(); + } +} diff --git a/context-object/src/test/java/com/iluwatar/contect/object/AppTest.java b/context-object/src/test/java/com/iluwatar/contect/object/AppTest.java new file mode 100644 index 000000000..d65cb440d --- /dev/null +++ b/context-object/src/test/java/com/iluwatar/contect/object/AppTest.java @@ -0,0 +1,17 @@ +package com.iluwatar.contect.object; + +import com.iluwatar.context.object.App; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +public class AppTest { + + /** + * Test example app runs without error. + */ + @Test + void shouldExecuteWithoutException() { + assertDoesNotThrow(() -> App.main(new String[]{})); + } +} diff --git a/context-object/src/test/java/com/iluwatar/contect/object/ServiceContextTest.java b/context-object/src/test/java/com/iluwatar/contect/object/ServiceContextTest.java new file mode 100644 index 000000000..48d9ce76b --- /dev/null +++ b/context-object/src/test/java/com/iluwatar/contect/object/ServiceContextTest.java @@ -0,0 +1,66 @@ +package com.iluwatar.contect.object; + +import com.iluwatar.context.object.LayerA; +import com.iluwatar.context.object.LayerB; +import com.iluwatar.context.object.LayerC; +import com.iluwatar.context.object.ServiceContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** + * Date: 10/24/2022 - 3:18 + * + * @author Chak Chan + */ +public class ServiceContextTest { + + private static final String SERVICE = "SERVICE"; + + private LayerA layerA; + + @BeforeEach + void initiateLayerA() { + this.layerA = new LayerA(); + } + + @Test + void testSameContextPassedBetweenLayers() { + ServiceContext context1 = layerA.getContext(); + var layerB = new LayerB(layerA); + ServiceContext context2 = layerB.getContext(); + var layerC = new LayerC(layerB); + ServiceContext context3 = layerC.getContext(); + + assertSame(context1, context2); + assertSame(context2, context3); + assertSame(context3, context1); + } + + @Test + void testScopedDataPassedBetweenLayers() { + layerA.addAccountInfo(SERVICE); + var layerB = new LayerB(layerA); + var layerC = new LayerC(layerB); + layerC.addSearchInfo(SERVICE); + ServiceContext context = layerC.getContext(); + + assertEquals(SERVICE,context.getAccountService()); + assertNull(context.getSessionService()); + assertEquals(SERVICE,context.getSearchService()); + } + + @Test + void testToString() { + assertEquals(layerA.getContext().toString(),"ServiceContext(AccountService=null, SessionService=null, SearchService=null)"); + layerA.addAccountInfo(SERVICE); + assertEquals(layerA.getContext().toString(), "ServiceContext(AccountService=SERVICE, SessionService=null, SearchService=null)"); + var layerB = new LayerB(layerA); + layerB.addSessionInfo(SERVICE); + var layerC = new LayerC(layerB); + assertEquals(layerC.getContext().toString(), "ServiceContext(AccountService=SERVICE, SessionService=SERVICE, SearchService=null)"); + } +}