Compare commits

..

2 Commits

Author SHA1 Message Date
Ilkka Seppälä
686fdf5812
fix checkstyle errors 2022-01-08 21:37:15 +02:00
Ilkka Seppälä
85ee24f90d
Refactor execute around idiom 2022-01-08 21:27:34 +02:00
35 changed files with 101 additions and 1130 deletions

View File

@ -1737,8 +1737,7 @@
"avatar_url": "https://avatars.githubusercontent.com/u/47126749?v=4",
"profile": "http://no website",
"contributions": [
"review",
"code"
"review"
]
},
{
@ -1786,24 +1785,6 @@
"contributions": [
"code"
]
},
{
"login": "ShivanshCharak",
"name": "ShivanshCharak",
"avatar_url": "https://avatars.githubusercontent.com/u/96943825?v=4",
"profile": "https://github.com/ShivanshCharak",
"contributions": [
"code"
]
},
{
"login": "HattoriHenzo",
"name": "HattoriHenzo",
"avatar_url": "https://avatars.githubusercontent.com/u/5141285?v=4",
"profile": "https://github.com/HattoriHenzo",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,

1
.gitignore vendored
View File

@ -12,7 +12,6 @@ tmp/
local.properties
.loadpath
.recommenders
.DS_Store
####### Java annotation processor (APT) ########
.factorypath

View File

@ -1,18 +1,25 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
#
# The MIT License
# Copyright © 2014-2021 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.
#
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

View File

@ -10,7 +10,7 @@
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-198-orange.svg?style=flat-square)](#contributors-)
[![All Contributors](https://img.shields.io/badge/all_contributors-196-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
<br/>
@ -320,17 +320,13 @@ This project is licensed under the terms of the MIT license.
</tr>
<tr>
<td align="center"><a href="https://www.linkedin.com/in/abhinav-vashisth-06613b208/"><img src="https://avatars.githubusercontent.com/u/89785800?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Abhinav Vashisth</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=vashisthabhinav" title="Documentation">📖</a></td>
<td align="center"><a href="http://no website"><img src="https://avatars.githubusercontent.com/u/47126749?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AKevinyl3" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/iluwatar/java-design-patterns/commits?author=Kevinyl3" title="Code">💻</a></td>
<td align="center"><a href="http://no website"><img src="https://avatars.githubusercontent.com/u/47126749?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AKevinyl3" title="Reviewed Pull Requests">👀</a></td>
<td align="center"><a href="https://github.com/Shrirang97"><img src="https://avatars.githubusercontent.com/u/28738668?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Shrirang</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AShrirang97" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/iluwatar/java-design-patterns/commits?author=Shrirang97" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/interactwithankush"><img src="https://avatars.githubusercontent.com/u/18613127?v=4?s=100" width="100px;" alt=""/><br /><sub><b>interactwithankush</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=interactwithankush" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/yuhangbin"><img src="https://avatars.githubusercontent.com/u/17566866?v=4?s=100" width="100px;" alt=""/><br /><sub><b>CharlieYu</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=yuhangbin" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Leisterbecker"><img src="https://avatars.githubusercontent.com/u/20650323?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Leisterbecker</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Leisterbecker" title="Code">💻</a></td>
<td align="center"><a href="http://rosaecrucis.cn"><img src="https://avatars.githubusercontent.com/u/35420129?v=4?s=100" width="100px;" alt=""/><br /><sub><b>DragonDreamer</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=castleKing1997" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/ShivanshCharak"><img src="https://avatars.githubusercontent.com/u/96943825?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ShivanshCharak</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ShivanshCharak" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/HattoriHenzo"><img src="https://avatars.githubusercontent.com/u/5141285?v=4?s=100" width="100px;" alt=""/><br /><sub><b>HattoriHenzo</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=HattoriHenzo" title="Code">💻</a></td>
</tr>
</table>
<!-- markdownlint-restore -->

View File

@ -29,7 +29,7 @@ import lombok.extern.slf4j.Slf4j;
* Hayes class implements its accept method.
*/
@Slf4j
public class Hayes implements Modem {
public class Hayes extends Modem {
/**
* Accepts all visitors but honors only HayesVisitor.

View File

@ -24,9 +24,8 @@
package com.iluwatar.acyclicvisitor;
/**
* //Modem abstract class.
* converted to an interface
* Modem abstract class.
*/
public interface Modem {
void accept(ModemVisitor modemVisitor);
public abstract class Modem {
public abstract void accept(ModemVisitor modemVisitor);
}

View File

@ -29,7 +29,7 @@ import lombok.extern.slf4j.Slf4j;
* Zoom class implements its accept method.
*/
@Slf4j
public class Zoom implements Modem {
public class Zoom extends Modem {
/**
* Accepts all visitors but honors only ZoomVisitor.

View File

@ -1,325 +0,0 @@
---
layout: pattern
title: Composite View
folder: composite-view
permalink: /patterns/composite-view/
categories: Structural
language: en
tags:
- Enterprise Integration Pattern
- Presentation
---
## Name
**Composite View**
## Intent
The purpose of the Composite View Pattern is to increase re-usability and flexibility when creating views for websites/webapps.
This pattern seeks to decouple the content of the page from its layout, allowing changes to be made to either the content
or layout of the page without impacting the other. This pattern also allows content to be easily reused across different views easily.
## Explanation
Real World Example
> A news site wants to display the current date and news to different users
> based on that user's preferences. The news site will substitute in different news feed
> components depending on the user's interest, defaulting to local news.
In Plain Words
> Composite View Pattern is having a main view being composed of smaller subviews.
> The layout of this composite view is based on a template. A View-manager then decides which
> subviews to include in this template.
Wikipedia Says
> Composite views that are composed of multiple atomic subviews. Each component of
> the template may be included dynamically into the whole and the layout of the page may be managed independently of the content.
> This solution provides for the creation of a composite view based on the inclusion and substitution of
> modular dynamic and static template fragments.
> It promotes the reuse of atomic portions of the view by encouraging modular design.
**Programmatic Example**
Since this is a web development pattern, a server is required to demonstrate it.
This example uses Tomcat 10.0.13 to run the servlet, and this programmatic example will only work with Tomcat 10+.
Firstly there is `AppServlet` which is an `HttpServlet` that runs on Tomcat 10+.
```java
public class AppServlet extends HttpServlet {
private String msgPartOne = "<h1>This Server Doesn't Support";
private String msgPartTwo = "Requests</h1>\n"
+ "<h2>Use a GET request with boolean values for the following parameters<h2>\n"
+ "<h3>'name'</h3>\n<h3>'bus'</h3>\n<h3>'sports'</h3>\n<h3>'sci'</h3>\n<h3>'world'</h3>";
private String destination = "newsDisplay.jsp";
public AppServlet() {
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
RequestDispatcher requestDispatcher = req.getRequestDispatcher(destination);
ClientPropertiesBean reqParams = new ClientPropertiesBean(req);
req.setAttribute("properties", reqParams);
requestDispatcher.forward(req, resp);
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
out.println(msgPartOne + " Post " + msgPartTwo);
}
@Override
public void doDelete(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
out.println(msgPartOne + " Delete " + msgPartTwo);
}
@Override
public void doPut(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
out.println(msgPartOne + " Put " + msgPartTwo);
}
}
```
This servlet is not part of the pattern, and simply forwards GET requests to the correct JSP.
PUT, POST, and DELETE requests are not supported and will simply show an error message.
The view management in this example is done via a javabean class: `ClientPropertiesBean`, which stores user preferences.
```java
public class ClientPropertiesBean implements Serializable {
private static final String WORLD_PARAM = "world";
private static final String SCIENCE_PARAM = "sci";
private static final String SPORTS_PARAM = "sport";
private static final String BUSINESS_PARAM = "bus";
private static final String NAME_PARAM = "name";
private static final String DEFAULT_NAME = "DEFAULT_NAME";
private boolean worldNewsInterest;
private boolean sportsInterest;
private boolean businessInterest;
private boolean scienceNewsInterest;
private String name;
public ClientPropertiesBean() {
worldNewsInterest = true;
sportsInterest = true;
businessInterest = true;
scienceNewsInterest = true;
name = DEFAULT_NAME;
}
public ClientPropertiesBean(HttpServletRequest req) {
worldNewsInterest = Boolean.parseBoolean(req.getParameter(WORLD_PARAM));
sportsInterest = Boolean.parseBoolean(req.getParameter(SPORTS_PARAM));
businessInterest = Boolean.parseBoolean(req.getParameter(BUSINESS_PARAM));
scienceNewsInterest = Boolean.parseBoolean(req.getParameter(SCIENCE_PARAM));
String tempName = req.getParameter(NAME_PARAM);
if (tempName == null || tempName == "") {
tempName = DEFAULT_NAME;
}
name = tempName;
}
// getters and setters generated by Lombok
}
```
This javabean has a default constructor, and another that takes an `HttpServletRequest`.
This second constructor takes the request object, parses out the request parameters which contain the
user preferences for different types of news.
The template for the news page is in `newsDisplay.jsp`
```html
<html>
<head>
<style>
h1 { text-align: center;}
h2 { text-align: center;}
h3 { text-align: center;}
.centerTable {
margin-left: auto;
margin-right: auto;
}
table {border: 1px solid black;}
tr {text-align: center;}
td {text-align: center;}
</style>
</head>
<body>
<%ClientPropertiesBean propertiesBean = (ClientPropertiesBean) request.getAttribute("properties");%>
<h1>Welcome <%= propertiesBean.getName()%></h1>
<jsp:include page="header.jsp"></jsp:include>
<table class="centerTable">
<tr>
<td></td>
<% if(propertiesBean.isWorldNewsInterest()) { %>
<td><%@include file="worldNews.jsp"%></td>
<% } else { %>
<td><%@include file="localNews.jsp"%></td>
<% } %>
<td></td>
</tr>
<tr>
<% if(propertiesBean.isBusinessInterest()) { %>
<td><%@include file="businessNews.jsp"%></td>
<% } else { %>
<td><%@include file="localNews.jsp"%></td>
<% } %>
<td></td>
<% if(propertiesBean.isSportsInterest()) { %>
<td><%@include file="sportsNews.jsp"%></td>
<% } else { %>
<td><%@include file="localNews.jsp"%></td>
<% } %>
</tr>
<tr>
<td></td>
<% if(propertiesBean.isScienceNewsInterest()) { %>
<td><%@include file="scienceNews.jsp"%></td>
<% } else { %>
<td><%@include file="localNews.jsp"%></td>
<% } %>
<td></td>
</tr>
</table>
</body>
</html>
```
This JSP page is the template. It declares a table with three rows, with one component in the first row,
two components in the second row, and one component in the third row.
The scriplets in the file are part of the
view management strategy that include different atomic subviews based on the user preferences in the Javabean.
Here are two examples of the mock atomic subviews used in the composite:
`businessNews.jsp`
```html
<html>
<head>
<style>
h2 { text-align: center;}
table {border: 1px solid black;}
tr {text-align: center;}
td {text-align: center;}
</style>
</head>
<body>
<h2>
Generic Business News
</h2>
<table style="margin-right: auto; margin-left: auto">
<tr>
<td>Stock prices up across the world</td>
<td>New tech companies to invest in</td>
</tr>
<tr>
<td>Industry leaders unveil new project</td>
<td>Price fluctuations and what they mean</td>
</tr>
</table>
</body>
</html>
```
`localNews.jsp`
```html
<html>
<body>
<div style="text-align: center">
<h3>
Generic Local News
</h3>
<ul style="list-style-type: none">
<li>
Mayoral elections coming up in 2 weeks
</li>
<li>
New parking meter rates downtown coming tomorrow
</li>
<li>
Park renovations to finish by the next year
</li>
<li>
Annual marathon sign ups available online
</li>
</ul>
</div>
</body>
</html>
```
The results are as such:
1) The user has put their name as `Tammy` in the request parameters and no preferences:
![alt text](etc/images/noparam.PNG)
2) The user has put their name as `Johnny` in the request parameters and has a preference for world, business, and science news:
![alt text](etc/images/threeparams.PNG)
The different subviews such as `worldNews.jsp`, `businessNews.jsp`, etc. are included conditionally
based on the request parameters.
**How To Use**
To try this example, make sure you have Tomcat 10+ installed.
Set up your IDE to build a WAR file from the module and deploy that file to the server
IntelliJ:
Under `Run` and `edit configurations` Make sure Tomcat server is one of the run configurations.
Go to the deployment tab, and make sure there is one artifact being built called `composite-view:war exploded`.
If not present, add one.
Ensure that the artifact is being built from the content of the `web` directory and the compilation results of the module.
Point the output of the artifact to a convenient place. Run the configuration and view the landing page,
follow instructions on that page to continue.
## Class diagram
![alt text](./etc/composite_view.png)
The class diagram here displays the Javabean which is the view manager.
The views are JSP's held inside the web directory.
## Applicability
This pattern is applicable to most websites that require content to be displayed dynamically/conditionally.
If there are components that need to be re-used for multiple views, or if the project requires reusing a template,
or if it needs to include content depending on certain conditions, then this pattern is a good choice.
## Known uses
Most modern websites use composite views in some shape or form, as they have templates for views and small atomic components
that are included in the page dynamically. Most modern Javascript libraries, like React, support this design pattern
with components.
## Consequences
**Pros**
* Easy to re-use components
* Change layout/content without affecting the other
* Reduce code duplication
* Code is more maintainable and modular
**Cons**
* Overhead cost at runtime
* Slower response compared to directly embedding elements
* Increases potential for display errors
## Related patterns
* [Composite (GoF)](https://java-design-patterns.com/patterns/composite/)
* [View Helper](https://www.oracle.com/java/technologies/viewhelper.html)
## Credits
* [Core J2EE Patterns - Composite View](https://www.oracle.com/java/technologies/composite-view.html)
* [Composite View Design Pattern Core J2EE Patterns](https://www.dineshonjava.com/composite-view-design-pattern/)

View File

@ -1,29 +0,0 @@
@startuml
package com.iluwatar.compositeview {
class ClientPropertiesBean {
- BUSINESS_PARAM : String {static}
- DEFAULT_NAME : String {static}
- NAME_PARAM : String {static}
- SCIENCE_PARAM : String {static}
- SPORTS_PARAM : String {static}
- WORLD_PARAM : String {static}
- businessInterest : boolean
- name : String
- scienceNewsInterest : boolean
- sportsInterest : boolean
- worldNewsInterest : boolean
+ ClientPropertiesBean()
+ ClientPropertiesBean(req : HttpServletRequest)
+ getName() : String
+ isBusinessInterest() : boolean
+ isScienceNewsInterest() : boolean
+ isSportsInterest() : boolean
+ isWorldNewsInterest() : boolean
+ setBusinessInterest(businessInterest : boolean)
+ setName(name : String)
+ setScienceNewsInterest(scienceNewsInterest : boolean)
+ setSportsInterest(sportsInterest : boolean)
+ setWorldNewsInterest(worldNewsInterest : boolean)
}
}
@enduml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

View File

@ -1,80 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The MIT License
Copyright © 2014-2021 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.
-->
<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">
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.26.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>composite-view</artifactId>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.1.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<configuration>
<archive>
<manifest>
<mainClass>com.iluwatar.compositeview.App</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,64 +0,0 @@
package com.iluwatar.compositeview;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* A servlet object that extends HttpServlet.
* Runs on Tomcat 10 and handles Http requests
*/
public final class AppServlet extends HttpServlet {
private String msgPartOne = "<h1>This Server Doesn't Support";
private String msgPartTwo = "Requests</h1>\n"
+ "<h2>Use a GET request with boolean values for the following parameters<h2>\n"
+ "<h3>'name'</h3>\n<h3>'bus'</h3>\n<h3>'sports'</h3>\n<h3>'sci'</h3>\n<h3>'world'</h3>";
private String destination = "newsDisplay.jsp";
public AppServlet() {
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
RequestDispatcher requestDispatcher = req.getRequestDispatcher(destination);
ClientPropertiesBean reqParams = new ClientPropertiesBean(req);
req.setAttribute("properties", reqParams);
requestDispatcher.forward(req, resp);
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/html");
try (PrintWriter out = resp.getWriter()) {
out.println(msgPartOne + " Post " + msgPartTwo);
}
}
@Override
public void doDelete(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/html");
try (PrintWriter out = resp.getWriter()) {
out.println(msgPartOne + " Delete " + msgPartTwo);
}
}
@Override
public void doPut(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/html");
try (PrintWriter out = resp.getWriter()) {
out.println(msgPartOne + " Put " + msgPartTwo);
}
}
}

View File

@ -1,53 +0,0 @@
package com.iluwatar.compositeview;
import jakarta.servlet.http.HttpServletRequest;
import java.io.Serializable;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* A Java beans class that parses a http request and stores parameters.
* Java beans used in JSP's to dynamically include elements in view.
* DEFAULT_NAME = a constant, default name to be used for the default constructor
* worldNewsInterest = whether current request has world news interest
* sportsInterest = whether current request has a sportsInterest
* businessInterest = whether current request has a businessInterest
* scienceNewsInterest = whether current request has a scienceNewsInterest
*/
@Getter
@Setter
@NoArgsConstructor
public class ClientPropertiesBean implements Serializable {
private static final String WORLD_PARAM = "world";
private static final String SCIENCE_PARAM = "sci";
private static final String SPORTS_PARAM = "sport";
private static final String BUSINESS_PARAM = "bus";
private static final String NAME_PARAM = "name";
private static final String DEFAULT_NAME = "DEFAULT_NAME";
private boolean worldNewsInterest = true;
private boolean sportsInterest = true;
private boolean businessInterest = true;
private boolean scienceNewsInterest = true;
private String name = DEFAULT_NAME;
/**
* Constructor that parses an HttpServletRequest and stores all the request parameters.
*
* @param req the HttpServletRequest object that is passed in
*/
public ClientPropertiesBean(HttpServletRequest req) {
worldNewsInterest = Boolean.parseBoolean(req.getParameter(WORLD_PARAM));
sportsInterest = Boolean.parseBoolean(req.getParameter(SPORTS_PARAM));
businessInterest = Boolean.parseBoolean(req.getParameter(BUSINESS_PARAM));
scienceNewsInterest = Boolean.parseBoolean(req.getParameter(SCIENCE_PARAM));
String tempName = req.getParameter(NAME_PARAM);
if (tempName == null || tempName.equals("")) {
tempName = DEFAULT_NAME;
}
name = tempName;
}
}

View File

@ -1,83 +0,0 @@
package com.iluwatar.compositeview;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.io.PrintWriter;
import java.io.StringWriter;
import static org.junit.Assert.*;
/* Written with reference from https://stackoverflow.com/questions/5434419/how-to-test-my-servlet-using-junit
and https://stackoverflow.com/questions/50211433/servlets-unit-testing
*/
public class AppServletTest extends Mockito{
private String msgPartOne = "<h1>This Server Doesn't Support";
private String msgPartTwo = "Requests</h1>\n"
+ "<h2>Use a GET request with boolean values for the following parameters<h2>\n"
+ "<h3>'name'</h3>\n<h3>'bus'</h3>\n<h3>'sports'</h3>\n<h3>'sci'</h3>\n<h3>'world'</h3>";
private String destination = "newsDisplay.jsp";
@Test
public void testDoGet() throws Exception {
HttpServletRequest mockReq = Mockito.mock(HttpServletRequest.class);
HttpServletResponse mockResp = Mockito.mock(HttpServletResponse.class);
RequestDispatcher mockDispatcher = Mockito.mock(RequestDispatcher.class);
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
when(mockResp.getWriter()).thenReturn(printWriter);
when(mockReq.getRequestDispatcher(destination)).thenReturn(mockDispatcher);
AppServlet curServlet = new AppServlet();
curServlet.doGet(mockReq, mockResp);
verify(mockReq, times(1)).getRequestDispatcher(destination);
verify(mockDispatcher).forward(mockReq, mockResp);
}
@Test
public void testDoPost() throws Exception {
HttpServletRequest mockReq = Mockito.mock(HttpServletRequest.class);
HttpServletResponse mockResp = Mockito.mock(HttpServletResponse.class);
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
when(mockResp.getWriter()).thenReturn(printWriter);
AppServlet curServlet = new AppServlet();
curServlet.doPost(mockReq, mockResp);
printWriter.flush();
assertTrue(stringWriter.toString().contains(msgPartOne + " Post " + msgPartTwo));
}
@Test
public void testDoPut() throws Exception {
HttpServletRequest mockReq = Mockito.mock(HttpServletRequest.class);
HttpServletResponse mockResp = Mockito.mock(HttpServletResponse.class);
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
when(mockResp.getWriter()).thenReturn(printWriter);
AppServlet curServlet = new AppServlet();
curServlet.doPut(mockReq, mockResp);
printWriter.flush();
assertTrue(stringWriter.toString().contains(msgPartOne + " Put " + msgPartTwo));
}
@Test
public void testDoDelete() throws Exception {
HttpServletRequest mockReq = Mockito.mock(HttpServletRequest.class);
HttpServletResponse mockResp = Mockito.mock(HttpServletResponse.class);
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
when(mockResp.getWriter()).thenReturn(printWriter);
AppServlet curServlet = new AppServlet();
curServlet.doDelete(mockReq, mockResp);
printWriter.flush();
assertTrue(stringWriter.toString().contains(msgPartOne + " Delete " + msgPartTwo));
}
}

View File

@ -1,71 +0,0 @@
package com.iluwatar.compositeview;
import jakarta.servlet.http.HttpServletRequest;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.junit.Assert.*;
public class JavaBeansTest {
@Test
public void testDefaultConstructor() {
ClientPropertiesBean newBean = new ClientPropertiesBean();
assertEquals("DEFAULT_NAME", newBean.getName());
assertTrue(newBean.isBusinessInterest());
assertTrue(newBean.isScienceNewsInterest());
assertTrue(newBean.isSportsInterest());
assertTrue(newBean.isWorldNewsInterest());
}
@Test
public void testNameGetterSetter() {
ClientPropertiesBean newBean = new ClientPropertiesBean();
assertEquals("DEFAULT_NAME", newBean.getName());
newBean.setName("TEST_NAME_ONE");
assertEquals("TEST_NAME_ONE", newBean.getName());
}
@Test
public void testBusinessSetterGetter() {
ClientPropertiesBean newBean = new ClientPropertiesBean();
assertTrue(newBean.isBusinessInterest());
newBean.setBusinessInterest(false);
assertFalse(newBean.isBusinessInterest());
}
@Test
public void testScienceSetterGetter() {
ClientPropertiesBean newBean = new ClientPropertiesBean();
assertTrue(newBean.isScienceNewsInterest());
newBean.setScienceNewsInterest(false);
assertFalse(newBean.isScienceNewsInterest());
}
@Test
public void testSportsSetterGetter() {
ClientPropertiesBean newBean = new ClientPropertiesBean();
assertTrue(newBean.isSportsInterest());
newBean.setSportsInterest(false);
assertFalse(newBean.isSportsInterest());
}
@Test
public void testWorldSetterGetter() {
ClientPropertiesBean newBean = new ClientPropertiesBean();
assertTrue(newBean.isWorldNewsInterest());
newBean.setWorldNewsInterest(false);
assertFalse(newBean.isWorldNewsInterest());
}
@Test
public void testRequestConstructor(){
HttpServletRequest mockReq = Mockito.mock(HttpServletRequest.class);
ClientPropertiesBean newBean = new ClientPropertiesBean((mockReq));
assertEquals("DEFAULT_NAME", newBean.getName());
assertFalse(newBean.isWorldNewsInterest());
assertFalse(newBean.isBusinessInterest());
assertFalse(newBean.isScienceNewsInterest());
assertFalse(newBean.isSportsInterest());
}
}

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>com.iluwatar.compositeview.AppServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/news</url-pattern>
</servlet-mapping>
</web-app>

View File

@ -1,33 +0,0 @@
<%--
Created by IntelliJ IDEA.
User: Kevin
Date: 11/29/2021
Time: 2:51 PM
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<style>
h2 { text-align: center;}
table {border: 1px solid black;}
tr {text-align: center;}
td {text-align: center;}
</style>
</head>
<body>
<h2>
Generic Business News
</h2>
<table style="margin-right: auto; margin-left: auto">
<tr>
<td>Stock prices up across the world</td>
<td>New tech companies to invest in</td>
</tr>
<tr>
<td>Industry leaders unveil new project</td>
<td>Price fluctuations and what they mean</td>
</tr>
</table>
</body>
</html>

View File

@ -1,23 +0,0 @@
<%--
Created by IntelliJ IDEA.
User: Kevin
Date: 11/29/2021
Time: 1:28 PM
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.Date"%>
<html>
<head>
<style>
h1 { text-align: center;}
h2 { text-align: center;}
h3 { text-align: center;}
</style>
</head>
<body>
<% String todayDateStr = (new Date().toString()); %>
<h1>Today's Personalized Frontpage</h1>
<h2><%=todayDateStr%></h2>
</body>
</html>

View File

@ -1,20 +0,0 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<style>
h1 { text-align: center;}
h2 { text-align: center;}
h3 { text-align: center;}
</style>
</head>
<body>
<h1>Welcome To The Composite Patterns Mock News Site</h1>
<h2>Send a GET request to the "/news" path to see the composite view with mock news</h2>
<h2>Use the following parameters:</h2>
<h3>name: string name to be dynamically displayed</h3>
<h3>bus: boolean for whether you want to see the mock business news</h3>
<h3>world: boolean for whether you want to see the mock world news</h3>
<h3>sci: boolean for whether you want to see the mock world news</h3>
<h3>sport: boolean for whether you want to see the mock world news</h3>
</body>
</html>

View File

@ -1,25 +0,0 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<div style="text-align: center">
<h3>
Generic Local News
</h3>
<ul style="list-style-type: none">
<li>
Mayoral elections coming up in 2 weeks
</li>
<li>
New parking meter rates downtown coming tomorrow
</li>
<li>
Park renovations to finish by the next year
</li>
<li>
Annual marathon sign ups available online
</li>
</ul>
</div>
</body>
</html>

View File

@ -1,57 +0,0 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="com.iluwatar.compositeview.ClientPropertiesBean"%>
<html>
<head>
<style>
h1 { text-align: center;}
h2 { text-align: center;}
h3 { text-align: center;}
.centerTable {
margin-left: auto;
margin-right: auto;
}
table {border: 1px solid black;}
tr {text-align: center;}
td {text-align: center;}
</style>
</head>
<body>
<%ClientPropertiesBean propertiesBean = (ClientPropertiesBean) request.getAttribute("properties");%>
<h1>Welcome <%= propertiesBean.getName()%></h1>
<jsp:include page="header.jsp"></jsp:include>
<table class="centerTable">
<tr>
<td></td>
<% if(propertiesBean.isWorldNewsInterest()) { %>
<td><%@include file="worldNews.jsp"%></td>
<% } else { %>
<td><%@include file="localNews.jsp"%></td>
<% } %>
<td></td>
</tr>
<tr>
<% if(propertiesBean.isBusinessInterest()) { %>
<td><%@include file="businessNews.jsp"%></td>
<% } else { %>
<td><%@include file="localNews.jsp"%></td>
<% } %>
<td></td>
<% if(propertiesBean.isSportsInterest()) { %>
<td><%@include file="sportsNews.jsp"%></td>
<% } else { %>
<td><%@include file="localNews.jsp"%></td>
<% } %>
</tr>
<tr>
<td></td>
<% if(propertiesBean.isScienceNewsInterest()) { %>
<td><%@include file="scienceNews.jsp"%></td>
<% } else { %>
<td><%@include file="localNews.jsp"%></td>
<% } %>
<td></td>
</tr>
</table>
</body>
</html>

View File

@ -1,34 +0,0 @@
<%--
Created by IntelliJ IDEA.
User: Kevin
Date: 11/29/2021
Time: 4:18 PM
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<div style="text-align: center">
<h3>
Generic Science News
</h3>
<ul>
<li>
New model of gravity proposed for dark matter
</li>
<li>
Genetic modifying technique proved on bacteria
</li>
<li>
Neurology study maps brain with new precision
</li>
<li>
Survey of rainforest discovers 15 new species
</li>
<li>
New signalling pathway for immune system discovered
</li>
</ul>
</div>
</body>
</html>

View File

@ -1,32 +0,0 @@
<%--
Created by IntelliJ IDEA.
User: Kevin
Date: 11/29/2021
Time: 3:53 PM
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<style>
h2 { text-align: center;}
table {border: 1px solid black;}
tr {text-align: center;}
td {text-align: center;}
</style>
</head>
<body>
<h2>
Generic Sports News
</h2>
<div style="margin-left: auto; margin-right: auto; padding: 20px">
International football match delayed due to weather, will be held next week
</div>
<div style="margin-left: auto; margin-right: auto; padding: 20px">
New rising stars in winter sports, ten new athletes that will shake up the scene
</div>
<div style="margin-left: auto; margin-right: auto; padding: 20px">
Biggest upset in basketball history, upstart team sweeps competition
</div>
</body>
</html>

View File

@ -1,34 +0,0 @@
<%--
Created by IntelliJ IDEA.
User: Kevin
Date: 11/29/2021
Time: 2:51 PM
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<style>
h2 { text-align: center;}
table {border: 1px solid black;}
tr {text-align: center;}
td {text-align: center;}
</style>
</head>
<body>
<h2>
Generic World News
</h2>
<table style="margin-right: auto; margin-left: auto">
<tr>
<td>New trade talks happening at UN on Thursday</td>
</tr>
<tr>
<td>European Union to announce new resolution next week</td>
</tr>
<tr>
<td>UN delivers report on world economic status</td>
</tr>
</table>
</body>
</html>

View File

@ -41,7 +41,7 @@
<zk.version>9.0.0</zk.version>
<guava.version>19.0</guava.version>
<jetty-maven-plugin.version>9.4.28.v20200408</jetty-maven-plugin.version>
<maven-war-plugin.version>3.3.2</maven-war-plugin.version>
<maven-war-plugin.version>2.1.1</maven-war-plugin.version>
<maven-assembly-plugin.version>2.2</maven-assembly-plugin.version>
<maven.build.timestamp.format>yyyy-MM-dd</maven.build.timestamp.format>
<packname>-${project.version}-FL-${maven.build.timestamp}</packname>

View File

@ -15,18 +15,18 @@ Registry
## Intent
Ensure a class only has a limited number of instances and provide a global point of access to them.
Ensure a class only has limited number of instances and provide a global point of access to them.
## Explanation
Real-world example
Real world example
> The Nazgûl, also called ringwraiths or the Nine Riders, are Sauron's most terrible servants. By
> definition, there's always nine of them.
> definition there's always nine of them.
In plain words
> Multiton pattern ensures there are a predefined amount of instances available globally.
> Multiton pattern ensures there's predefined amount of instances available globally.
Wikipedia says
@ -81,54 +81,29 @@ public final class Nazgul {
And here's how we access the `Nazgul` instances.
```java
// eagerly initialized multiton
LOGGER.info("Printing out eagerly initialized multiton contents");
LOGGER.info("KHAMUL={}", Nazgul.getInstance(NazgulName.KHAMUL));
LOGGER.info("MURAZOR={}", Nazgul.getInstance(NazgulName.MURAZOR));
LOGGER.info("DWAR={}", Nazgul.getInstance(NazgulName.DWAR));
LOGGER.info("JI_INDUR={}", Nazgul.getInstance(NazgulName.JI_INDUR));
LOGGER.info("AKHORAHIL={}", Nazgul.getInstance(NazgulName.AKHORAHIL));
LOGGER.info("HOARMURATH={}", Nazgul.getInstance(NazgulName.HOARMURATH));
LOGGER.info("ADUNAPHEL={}", Nazgul.getInstance(NazgulName.ADUNAPHEL));
LOGGER.info("REN={}", Nazgul.getInstance(NazgulName.REN));
LOGGER.info("UVATHA={}", Nazgul.getInstance(NazgulName.UVATHA));
// enum multiton
LOGGER.info("Printing out enum-based multiton contents");
LOGGER.info("KHAMUL={}", NazgulEnum.KHAMUL);
LOGGER.info("MURAZOR={}", NazgulEnum.MURAZOR);
LOGGER.info("DWAR={}", NazgulEnum.DWAR);
LOGGER.info("JI_INDUR={}", NazgulEnum.JI_INDUR);
LOGGER.info("AKHORAHIL={}", NazgulEnum.AKHORAHIL);
LOGGER.info("HOARMURATH={}", NazgulEnum.HOARMURATH);
LOGGER.info("ADUNAPHEL={}", NazgulEnum.ADUNAPHEL);
LOGGER.info("REN={}", NazgulEnum.REN);
LOGGER.info("UVATHA={}", NazgulEnum.UVATHA);
LOGGER.info("KHAMUL={}", Nazgul.getInstance(NazgulName.KHAMUL));
LOGGER.info("MURAZOR={}", Nazgul.getInstance(NazgulName.MURAZOR));
LOGGER.info("DWAR={}", Nazgul.getInstance(NazgulName.DWAR));
LOGGER.info("JI_INDUR={}", Nazgul.getInstance(NazgulName.JI_INDUR));
LOGGER.info("AKHORAHIL={}", Nazgul.getInstance(NazgulName.AKHORAHIL));
LOGGER.info("HOARMURATH={}", Nazgul.getInstance(NazgulName.HOARMURATH));
LOGGER.info("ADUNAPHEL={}", Nazgul.getInstance(NazgulName.ADUNAPHEL));
LOGGER.info("REN={}", Nazgul.getInstance(NazgulName.REN));
LOGGER.info("UVATHA={}", Nazgul.getInstance(NazgulName.UVATHA));
```
Program output:
```
20:35:07.413 [main] INFO com.iluwatar.multiton.App - Printing out eagerly initialized multiton contents
20:35:07.417 [main] INFO com.iluwatar.multiton.App - KHAMUL=com.iluwatar.multiton.Nazgul@48cf768c
20:35:07.419 [main] INFO com.iluwatar.multiton.App - MURAZOR=com.iluwatar.multiton.Nazgul@7960847b
20:35:07.419 [main] INFO com.iluwatar.multiton.App - DWAR=com.iluwatar.multiton.Nazgul@6a6824be
20:35:07.419 [main] INFO com.iluwatar.multiton.App - JI_INDUR=com.iluwatar.multiton.Nazgul@5c8da962
20:35:07.419 [main] INFO com.iluwatar.multiton.App - AKHORAHIL=com.iluwatar.multiton.Nazgul@512ddf17
20:35:07.419 [main] INFO com.iluwatar.multiton.App - HOARMURATH=com.iluwatar.multiton.Nazgul@2c13da15
20:35:07.419 [main] INFO com.iluwatar.multiton.App - ADUNAPHEL=com.iluwatar.multiton.Nazgul@77556fd
20:35:07.419 [main] INFO com.iluwatar.multiton.App - REN=com.iluwatar.multiton.Nazgul@368239c8
20:35:07.420 [main] INFO com.iluwatar.multiton.App - UVATHA=com.iluwatar.multiton.Nazgul@9e89d68
20:35:07.420 [main] INFO com.iluwatar.multiton.App - Printing out enum-based multiton contents
20:35:07.420 [main] INFO com.iluwatar.multiton.App - KHAMUL=KHAMUL
20:35:07.420 [main] INFO com.iluwatar.multiton.App - MURAZOR=MURAZOR
20:35:07.420 [main] INFO com.iluwatar.multiton.App - DWAR=DWAR
20:35:07.420 [main] INFO com.iluwatar.multiton.App - JI_INDUR=JI_INDUR
20:35:07.421 [main] INFO com.iluwatar.multiton.App - AKHORAHIL=AKHORAHIL
20:35:07.421 [main] INFO com.iluwatar.multiton.App - HOARMURATH=HOARMURATH
20:35:07.421 [main] INFO com.iluwatar.multiton.App - ADUNAPHEL=ADUNAPHEL
20:35:07.421 [main] INFO com.iluwatar.multiton.App - REN=REN
20:35:07.421 [main] INFO com.iluwatar.multiton.App - UVATHA=UVATHA
KHAMUL=com.iluwatar.multiton.Nazgul@2b214b94
MURAZOR=com.iluwatar.multiton.Nazgul@17814b1c
DWAR=com.iluwatar.multiton.Nazgul@7ac9af2a
JI_INDUR=com.iluwatar.multiton.Nazgul@7bb004b8
AKHORAHIL=com.iluwatar.multiton.Nazgul@78e89bfe
HOARMURATH=com.iluwatar.multiton.Nazgul@652ce654
ADUNAPHEL=com.iluwatar.multiton.Nazgul@522ba524
REN=com.iluwatar.multiton.Nazgul@29c5ee1d
UVATHA=com.iluwatar.multiton.Nazgul@15cea7b0
```
## Class diagram
@ -139,5 +114,5 @@ Program output:
Use the Multiton pattern when
* There must be a specific number of instances of a class, and they must be accessible to clients from
* There must be specific number of instances of a class, and they must be accessible to clients from
a well-known access point.

View File

@ -26,13 +26,13 @@ package com.iluwatar.multiton;
import lombok.extern.slf4j.Slf4j;
/**
* Whereas Singleton design pattern introduces single globally accessible object, the Multiton
* Whereas Singleton design pattern introduces single globally accessible object the Multiton
* pattern defines many globally accessible objects. The client asks for the correct instance from
* the Multiton by passing an enumeration as a parameter.
* the Multiton by passing an enumeration as parameter.
*
* <p>There is more than one way to implement the multiton design pattern. In the first example
* {@link Nazgul} is the Multiton and we can ask single {@link Nazgul} from it using {@link
* NazgulName}. The {@link Nazgul}s are statically initialized and stored in a concurrent hash map.
* NazgulName}. The {@link Nazgul}s are statically initialized and stored in concurrent hash map.
*
* <p>In the enum implementation {@link NazgulEnum} is the multiton. It is static and mutable
* because of the way java supports enums.
@ -47,7 +47,6 @@ public class App {
*/
public static void main(String[] args) {
// eagerly initialized multiton
LOGGER.info("Printing out eagerly initialized multiton contents");
LOGGER.info("KHAMUL={}", Nazgul.getInstance(NazgulName.KHAMUL));
LOGGER.info("MURAZOR={}", Nazgul.getInstance(NazgulName.MURAZOR));
LOGGER.info("DWAR={}", Nazgul.getInstance(NazgulName.DWAR));
@ -59,7 +58,6 @@ public class App {
LOGGER.info("UVATHA={}", Nazgul.getInstance(NazgulName.UVATHA));
// enum multiton
LOGGER.info("Printing out enum-based multiton contents");
LOGGER.info("KHAMUL={}", NazgulEnum.KHAMUL);
LOGGER.info("MURAZOR={}", NazgulEnum.MURAZOR);
LOGGER.info("DWAR={}", NazgulEnum.DWAR);

View File

@ -48,4 +48,5 @@ public class NazgulTest {
assertEquals(name, nazgul.getName());
}
}
}

18
mvnw vendored
View File

@ -36,10 +36,6 @@
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
@ -149,7 +145,7 @@ if [ -z "$JAVACMD" ] ; then
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`\\unset -f command; \\command -v java`"
JAVACMD="`which java`"
fi
fi
@ -216,9 +212,9 @@ else
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
@ -237,9 +233,9 @@ else
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
@ -309,8 +305,6 @@ WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

66
mvnw.cmd vendored
View File

@ -1,21 +1,25 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM The MIT License
@REM Copyright © 2014-2021 Ilkka Seppälä
@REM
@REM Permission is hereby granted, free of charge, to any person obtaining a copy
@REM of this software and associated documentation files (the "Software"), to deal
@REM in the Software without restriction, including without limitation the rights
@REM to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
@REM copies of the Software, and to permit persons to whom the Software is
@REM furnished to do so, subject to the following conditions:
@REM
@REM The above copyright notice and this permission notice shall be included in
@REM all copies or substantial portions of the Software.
@REM
@REM THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
@REM IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@REM FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@REM AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
@REM LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
@REM OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
@REM THE SOFTWARE.
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@ -46,8 +50,8 @@ if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
@ -120,9 +124,9 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@ -134,7 +138,7 @@ if exist %WRAPPER_JAR% (
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
@ -158,13 +162,7 @@ if exist %WRAPPER_JAR% (
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
@ -174,15 +172,15 @@ set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%
exit /B %ERROR_CODE%

1
naked-objects/README Normal file
View File

@ -0,0 +1 @@
This is an Apache Isis application created with the SimpleApp archetype. The usage instructions can be found at http://isis.apache.org/guides/ug.html#_ug_getting-started_simpleapp-archetype

View File

@ -150,7 +150,7 @@
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<version>2.4</version>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>

View File

@ -228,7 +228,6 @@
<module>lockable-object</module>
<module>fanout-fanin</module>
<module>domain-model</module>
<module>composite-view</module>
<module>metadata-mapping</module>
</modules>
<repositories>