diff --git a/client-session/README.md b/client-session/README.md
new file mode 100644
index 000000000..82204eb34
--- /dev/null
+++ b/client-session/README.md
@@ -0,0 +1,114 @@
+---
+title: Client Session Pattern
+category: Architectural
+language: en
+tags:
+- Decoupling
+---
+
+## Name
+
+[Client Session pattern](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-client)
+
+## Intent
+
+- Create stateless servers that removes the problem of clustering, as users can switch between servers seamlessly.
+- Makes data more resilient in case of server fail-over.
+- Works well with smaller data sizes.
+
+## Explanation
+
+Real-World Example
+
+> You're looking to create a data management app allowing users to send requests to the server to
+> modify and make changes to data stored on their devices. These requests are small in size and the
+> data is individual to each user, negating the need for a large scale database implementation.
+> Using the client session pattern, you are able to handle multiple concurrent requests, load
+> balancing clients across different servers with ease due to servers remaining stateless. You also
+> remove the need to store session IDs on the server side due to clients providing all the
+> information that a server needs to perform their process.
+
+In Plain words
+
+> Instead of storing information about the current client and the information being accessed on the
+> server, it is maintained client side only. Client has to send session data with each request to
+> the server and has to send an updated state back to the client, which is stored on the clients
+> machine. The server doesn't have to store the client information.
+> ([ref](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-client))
+
+**Programmatic Example**
+
+Here is the sample code to describe the client-session pattern. In the below code we are first
+creating an instance of the Server. This server instance will then be used to get Session objects
+for two clients. As you can see from the code below the Session object can be used to store any
+relevant information that are required by the server to process the client request. These session
+objects will then be passed on with every Request to the server. The Request will have the Session
+object that stores the relevant client details along with the required data for processing the
+request. The session information in every request helps the server identify the client and process
+the request accordingly.
+
+```java
+public class App {
+
+ public static void main(String[] args) {
+ var server = new Server("localhost", 8080);
+ var session1 = server.getSession("Session1");
+ var session2 = server.getSession("Session2");
+ var request1 = new Request("Data1", session1);
+ var request2 = new Request("Data2", session2);
+ server.process(request1);
+ server.process(request2);
+ }
+}
+
+@Data
+@AllArgsConstructor
+public class Session {
+
+ /**
+ * Session id.
+ */
+ private String id;
+
+ /**
+ * Client name.
+ */
+ private String clientName;
+
+}
+
+@Data
+@AllArgsConstructor
+public class Request {
+
+ private String data;
+
+ private Session session;
+
+}
+```
+
+## Architecture Diagram
+
+
+
+## Applicability
+
+Use the client state pattern when:
+
+- Processing smaller amounts of data to prevent larger requests and response sizes.
+- Remove the need for servers to save client states. Doing so also removes the need to store session IDs.
+- Clustering is an issue and needs to be avoided. Stateless servers allow clients to be easily distributed across servers.
+- Creates resilience from data losses due to server fails.
+
+## Consequences
+
+- The server is stateless. Any compute API will not store any data.
+- Struggles to deal with large amounts of data. Creates longer send and receive times due to larger amounts of session data to manage.
+- Security. All data is stored on the client's machine. This means that any vulnerabilities on the clients side can expose all data being sent and received by the server.
+
+
+## Credits
+
+- [Dzone - Practical PHP patterns](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-client)
+- [Client Session State Design Pattern - Ram N Java](https://www.youtube.com/watch?v=ycOSj9g41pc)
diff --git a/client-session/etc/session_state_pattern.png b/client-session/etc/session_state_pattern.png
new file mode 100644
index 000000000..f1e23be95
Binary files /dev/null and b/client-session/etc/session_state_pattern.png differ
diff --git a/client-session/pom.xml b/client-session/pom.xml
new file mode 100644
index 000000000..b7ff08637
--- /dev/null
+++ b/client-session/pom.xml
@@ -0,0 +1,62 @@
+
+
+
In this example, The {@link Server} class represents the server that would process the + * incoming {@link Request} and also assign {@link Session} to a client. Here one instance of Server + * is created. The we create two sessions for two different clients. These sessions are then passed + * on to the server in the request along with the data. The server is then able to interpret the + * client based on the session associated with it. + *
+ */ +public class App { + + /** + * Program entry point. + * + * @param args Command line args + */ + public static void main(String[] args) { + var server = new Server("localhost", 8080); + var session1 = server.getSession("Session1"); + var session2 = server.getSession("Session2"); + var request1 = new Request("Data1", session1); + var request2 = new Request("Data2", session2); + server.process(request1); + server.process(request2); + } +} diff --git a/client-session/src/main/java/com/iluwatar/client/session/Request.java b/client-session/src/main/java/com/iluwatar/client/session/Request.java new file mode 100644 index 000000000..008011f18 --- /dev/null +++ b/client-session/src/main/java/com/iluwatar/client/session/Request.java @@ -0,0 +1,42 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.client.session; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * The Request class which contains the Session details and data. + */ +@Data +@AllArgsConstructor +public class Request { + + private String data; + + private Session session; + +} diff --git a/client-session/src/main/java/com/iluwatar/client/session/Server.java b/client-session/src/main/java/com/iluwatar/client/session/Server.java new file mode 100644 index 000000000..6d9dc3dbc --- /dev/null +++ b/client-session/src/main/java/com/iluwatar/client/session/Server.java @@ -0,0 +1,65 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.client.session; + +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +/** + * The Server class. The client communicates with the server and request processing and getting a new session. + */ +@Slf4j +@Data +@AllArgsConstructor +public class Server { + private String host; + + private int port; + + + /** + * Creates a new session. + * + * @param name name of the client + * + * @return Session Object + */ + public Session getSession(String name) { + return new Session(UUID.randomUUID().toString(), name); + } + + /** + * Processes a request based on the session. + * + * @param request Request object with data and Session + */ + public void process(Request request) { + LOGGER.info("Processing Request with client: " + request.getSession().getClientName() + " data: " + request.getData()); + } + +} diff --git a/client-session/src/main/java/com/iluwatar/client/session/Session.java b/client-session/src/main/java/com/iluwatar/client/session/Session.java new file mode 100644 index 000000000..bb9f7246c --- /dev/null +++ b/client-session/src/main/java/com/iluwatar/client/session/Session.java @@ -0,0 +1,48 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.client.session; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * The Session class. Each client get assigned a Session which is then used for further communications. + */ +@Data +@AllArgsConstructor +public class Session { + + /** + * Session id. + */ + private String id; + + /** + * Client name. + */ + private String clientName; + +} diff --git a/client-session/src/test/java/com/iluwatar/client/session/AppTest.java b/client-session/src/test/java/com/iluwatar/client/session/AppTest.java new file mode 100644 index 000000000..0e33f74f4 --- /dev/null +++ b/client-session/src/test/java/com/iluwatar/client/session/AppTest.java @@ -0,0 +1,38 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.client.session; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import org.junit.jupiter.api.Test; + +class AppTest { + + @Test + void appStartsWithoutException() { + assertDoesNotThrow(() -> App.main(new String[]{})); + } +} diff --git a/client-session/src/test/java/com/iluwatar/client/session/ServerTest.java b/client-session/src/test/java/com/iluwatar/client/session/ServerTest.java new file mode 100644 index 000000000..dc09441f0 --- /dev/null +++ b/client-session/src/test/java/com/iluwatar/client/session/ServerTest.java @@ -0,0 +1,14 @@ +package com.iluwatar.client.session; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ServerTest { + + @Test + void checkGetSession() { + Server server = new Server("localhost", 8080); + Session session = server.getSession("Session"); + assertEquals("Session", session.getClientName()); + } +} diff --git a/pom.xml b/pom.xml index 09e4dea4f..90c4b2941 100644 --- a/pom.xml +++ b/pom.xml @@ -198,6 +198,7 @@