Skip to content

Commit 4f1cf37

Browse files
authored
chore: upgrade users sample from java8 to java21 (#10153)
* chore: Upgrade users sample from java8 to java21 * fix: update pom to java21 * fix: import order * chore: set app-engine-apis to true * fix: license header * chore: use EE8 instead of EE10 * chore: upgrade dependencies * fix: cloudshell url
1 parent 5c82990 commit 4f1cf37

File tree

6 files changed

+357
-0
lines changed

6 files changed

+357
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Users Authentication sample for Google App Engine
2+
3+
<a href="https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/java-docs-samples&page=editor&open_in_editor=appengine-java21/ee8/users/README.md">
4+
<img alt="Open in Cloud Shell" src ="http://gstatic.com/cloudssh/images/open-btn.png"></a>
5+
6+
This sample demonstrates how to use the [Users API][appid] on [Google App
7+
Engine][ae-docs].
8+
9+
[appid]: https://cloud.google.com/appengine/docs/java/users/
10+
[ae-docs]: https://cloud.google.com/appengine/docs/java/
11+
12+
## Running locally
13+
This example uses the
14+
[Maven gcloud plugin](https://cloud.google.com/appengine/docs/legacy/standard/java/using-maven).
15+
To run this sample locally:
16+
17+
$ mvn appengine:run
18+
19+
## Deploying
20+
In the following command, replace YOUR-PROJECT-ID with your
21+
[Google Cloud Project ID](https://developers.google.com/console/help/new/#projectnumber).
22+
23+
$ mvn clean package appengine:deploy

appengine-java21/ee8/users/pom.xml

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Copyright 2015 Google LLC
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<project xmlns="http://maven.apache.org/POM/4.0.0"
18+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20+
<modelVersion>4.0.0</modelVersion>
21+
<packaging>war</packaging>
22+
<version>1.0-SNAPSHOT</version>
23+
<groupId>com.example.appengine</groupId>
24+
<artifactId>appengine-users-j21</artifactId>
25+
26+
<!--
27+
The parent pom defines common style checks and testing strategies for our samples.
28+
Removing or replacing it should not affect the execution of the samples in anyway.
29+
-->
30+
<parent>
31+
<groupId>com.google.cloud.samples</groupId>
32+
<artifactId>shared-configuration</artifactId>
33+
<version>1.2.0</version>
34+
</parent>
35+
<properties>
36+
<maven.compiler.target>21</maven.compiler.target>
37+
<maven.compiler.source>21</maven.compiler.source>
38+
</properties>
39+
40+
<dependencyManagement>
41+
<dependencies>
42+
<dependency>
43+
<artifactId>libraries-bom</artifactId>
44+
<groupId>com.google.cloud</groupId>
45+
<scope>import</scope>
46+
<type>pom</type>
47+
<version>26.28.0</version>
48+
</dependency>
49+
</dependencies>
50+
</dependencyManagement>
51+
52+
<dependencies>
53+
<dependency>
54+
<groupId>com.google.appengine</groupId>
55+
<artifactId>appengine-api-1.0-sdk</artifactId>
56+
<version>2.0.39</version>
57+
</dependency>
58+
59+
<dependency>
60+
<groupId>jakarta.servlet</groupId>
61+
<artifactId>jakarta.servlet-api</artifactId>
62+
<version>4.0.4</version>
63+
<type>jar</type>
64+
<scope>provided</scope>
65+
</dependency>
66+
67+
<!-- Test Dependencies -->
68+
<dependency>
69+
<groupId>junit</groupId>
70+
<artifactId>junit</artifactId>
71+
<version>4.13.2</version>
72+
<scope>test</scope>
73+
</dependency>
74+
<dependency>
75+
<groupId>org.mockito</groupId>
76+
<artifactId>mockito-core</artifactId>
77+
<version>4.11.0</version>
78+
<scope>test</scope>
79+
</dependency>
80+
<dependency>
81+
<groupId>com.google.appengine</groupId>
82+
<artifactId>appengine-testing</artifactId>
83+
<version>2.0.39</version>
84+
<scope>test</scope>
85+
</dependency>
86+
<dependency>
87+
<groupId>com.google.appengine</groupId>
88+
<artifactId>appengine-api-stubs</artifactId>
89+
<version>2.0.39</version>
90+
<scope>test</scope>
91+
</dependency>
92+
<dependency>
93+
<groupId>com.google.appengine</groupId>
94+
<artifactId>appengine-tools-sdk</artifactId>
95+
<version>2.0.39</version>
96+
<scope>test</scope>
97+
</dependency>
98+
<dependency>
99+
<groupId>com.google.truth</groupId>
100+
<artifactId>truth</artifactId>
101+
<version>1.4.4</version>
102+
<scope>test</scope>
103+
</dependency>
104+
105+
</dependencies>
106+
<build>
107+
<!-- for hot reload of the web application -->
108+
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>
109+
<plugins>
110+
<plugin>
111+
<groupId>org.apache.maven.plugins</groupId>
112+
<artifactId>maven-war-plugin</artifactId>
113+
<version>3.4.0</version>
114+
</plugin>
115+
<plugin>
116+
<groupId>org.jacoco</groupId>
117+
<artifactId>jacoco-maven-plugin</artifactId>
118+
<version>0.8.13</version>
119+
</plugin>
120+
<plugin>
121+
<groupId>com.google.cloud.tools</groupId>
122+
<artifactId>appengine-maven-plugin</artifactId>
123+
<version>2.5.0</version>
124+
<configuration>
125+
<projectId>GCLOUD_CONFIG</projectId>
126+
<version>GCLOUD_CONFIG</version>
127+
<deploy.promote>true</deploy.promote>
128+
<deploy.stopPreviousVersion>true</deploy.stopPreviousVersion>
129+
</configuration>
130+
</plugin>
131+
</plugins>
132+
</build>
133+
</project>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* Copyright 2016 Google LLC
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
// [START gae_java21_users_api]
17+
18+
package com.example.appengine.users;
19+
20+
import com.google.appengine.api.users.UserService;
21+
import com.google.appengine.api.users.UserServiceFactory;
22+
import java.io.IOException;
23+
import javax.servlet.annotation.WebServlet;
24+
import javax.servlet.http.HttpServlet;
25+
import javax.servlet.http.HttpServletRequest;
26+
import javax.servlet.http.HttpServletResponse;
27+
28+
// With @WebServlet annotation the webapp/WEB-INF/web.xml is no longer required.
29+
@WebServlet(
30+
name = "UserAPI",
31+
description = "UserAPI: Login / Logout with UserService",
32+
urlPatterns = "/userapi"
33+
)
34+
public class UsersServlet extends HttpServlet {
35+
36+
@Override
37+
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
38+
UserService userService = UserServiceFactory.getUserService();
39+
40+
String thisUrl = req.getRequestURI();
41+
42+
resp.setContentType("text/html");
43+
if (req.getUserPrincipal() != null) {
44+
resp.getWriter()
45+
.println(
46+
"<p>Hello, "
47+
+ req.getUserPrincipal().getName()
48+
+ "! You can <a href=\""
49+
+ userService.createLogoutURL(thisUrl)
50+
+ "\">sign out</a>.</p>");
51+
} else {
52+
resp.getWriter()
53+
.println(
54+
"<p>Please <a href=\"" + userService.createLoginURL(thisUrl) + "\">sign in</a>.</p>");
55+
}
56+
}
57+
}
58+
// [END gae_java21_users_api]
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
3+
<runtime>java21</runtime>
4+
<system-properties>
5+
<property name="appengine.use.EE8" value="true"/>
6+
</system-properties>
7+
<app-engine-apis>true</app-engine-apis>
8+
</appengine-web-app>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright 2017 Google LLC
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
18+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19+
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
20+
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
21+
version="6.0">
22+
<welcome-file-list>
23+
<welcome-file>userapi</welcome-file>
24+
</welcome-file-list>
25+
<app-engine-apis>true</app-engine-apis>
26+
</web-app>
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright 2015 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.appengine.users;
18+
19+
import static com.google.common.truth.Truth.assertWithMessage;
20+
import static org.mockito.Mockito.when;
21+
22+
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
23+
import java.io.PrintWriter;
24+
import java.io.StringWriter;
25+
import javax.management.remote.JMXPrincipal;
26+
import javax.servlet.http.HttpServletRequest;
27+
import javax.servlet.http.HttpServletResponse;
28+
import org.junit.After;
29+
import org.junit.Before;
30+
import org.junit.Test;
31+
import org.junit.runner.RunWith;
32+
import org.junit.runners.JUnit4;
33+
import org.mockito.Mock;
34+
import org.mockito.MockitoAnnotations;
35+
36+
/**
37+
* Unit tests for {@link UsersServlet}.
38+
*/
39+
@RunWith(JUnit4.class)
40+
public class UsersServletTest {
41+
42+
private static final String FAKE_URL = "fakey.fake.fak";
43+
private static final String FAKE_NAME = "Fake";
44+
// Set up a helper so that the ApiProxy returns a valid environment for local testing.
45+
private final LocalServiceTestHelper helper = new LocalServiceTestHelper();
46+
47+
@Mock
48+
private HttpServletRequest mockRequestNotLoggedIn;
49+
@Mock
50+
private HttpServletRequest mockRequestLoggedIn;
51+
@Mock
52+
private HttpServletResponse mockResponse;
53+
private StringWriter responseWriter;
54+
private UsersServlet servletUnderTest;
55+
56+
@Before
57+
public void setUp() throws Exception {
58+
MockitoAnnotations.openMocks(this);
59+
helper.setUp();
60+
61+
// Set up some fake HTTP requests
62+
// If the user isn't logged in, use this request
63+
when(mockRequestNotLoggedIn.getRequestURI()).thenReturn(FAKE_URL);
64+
when(mockRequestNotLoggedIn.getUserPrincipal()).thenReturn(null);
65+
66+
// If the user is logged in, use this request
67+
when(mockRequestLoggedIn.getRequestURI()).thenReturn(FAKE_URL);
68+
// Most of the classes that implement Principal have been
69+
// deprecated. JMXPrincipal seems like a safe choice.
70+
when(mockRequestLoggedIn.getUserPrincipal()).thenReturn(new JMXPrincipal(FAKE_NAME));
71+
72+
// Set up a fake HTTP response.
73+
responseWriter = new StringWriter();
74+
when(mockResponse.getWriter()).thenReturn(new PrintWriter(responseWriter));
75+
76+
servletUnderTest = new UsersServlet();
77+
}
78+
79+
@After
80+
public void tearDown() {
81+
helper.tearDown();
82+
}
83+
84+
@Test
85+
public void doGet_userNotLoggedIn_writesResponse() throws Exception {
86+
servletUnderTest.doGet(mockRequestNotLoggedIn, mockResponse);
87+
88+
// If a user isn't logged in, we expect a prompt
89+
// to login to be returned.
90+
assertWithMessage("UsersServlet response")
91+
.that(responseWriter.toString())
92+
.contains("<p>Please <a href=");
93+
assertWithMessage("UsersServlet response")
94+
.that(responseWriter.toString())
95+
.contains("sign in</a>.</p>");
96+
}
97+
98+
@Test
99+
public void doGet_userLoggedIn_writesResponse() throws Exception {
100+
servletUnderTest.doGet(mockRequestLoggedIn, mockResponse);
101+
102+
// If a user is logged in, we expect a prompt
103+
// to logout to be returned.
104+
assertWithMessage("UsersServlet response")
105+
.that(responseWriter.toString())
106+
.contains("<p>Hello, " + FAKE_NAME + "!");
107+
assertWithMessage("UsersServlet response").that(responseWriter.toString()).contains("sign out");
108+
}
109+
}

0 commit comments

Comments
 (0)