diff --git a/grails-test-examples/jetty/build.gradle b/grails-test-examples/jetty/build.gradle
new file mode 100644
index 00000000000..036352bf585
--- /dev/null
+++ b/grails-test-examples/jetty/build.gradle
@@ -0,0 +1,64 @@
+/*
+ * 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
+ *
+ * https://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.
+ */
+plugins {
+ id 'org.apache.grails.buildsrc.properties'
+ id 'org.apache.grails.buildsrc.dependency-validator'
+ id 'org.apache.grails.buildsrc.compile'
+}
+
+version = '0.1'
+group = 'issue12688'
+
+apply plugin: 'org.apache.grails.gradle.grails-web'
+apply plugin: 'org.apache.grails.gradle.grails-gsp'
+apply plugin: 'cloud.wondrify.asset-pipeline'
+
+dependencies {
+ implementation platform(project(':grails-bom'))
+
+ implementation 'org.springframework.boot:spring-boot-starter-logging'
+ implementation 'org.springframework.boot:spring-boot-autoconfigure'
+ implementation 'org.apache.grails:grails-core'
+ implementation 'org.springframework.boot:spring-boot-starter-actuator'
+ implementation 'org.springframework.boot:spring-boot-starter-jetty'
+ implementation 'org.apache.grails:grails-web-boot'
+ implementation 'org.apache.grails:grails-layout'
+ implementation 'org.apache.grails:grails-logging'
+ implementation 'org.apache.grails:grails-rest-transforms'
+ implementation 'org.apache.grails:grails-databinding'
+ implementation 'org.apache.grails:grails-services'
+ implementation 'org.apache.grails:grails-url-mappings'
+ implementation 'org.apache.grails:grails-interceptors'
+ implementation 'org.apache.grails:grails-gsp'
+
+ testAndDevelopmentOnly platform(project(':grails-bom'))
+ testAndDevelopmentOnly 'org.webjars.npm:bootstrap'
+ testAndDevelopmentOnly 'org.webjars.npm:jquery'
+
+ runtimeOnly 'cloud.wondrify:asset-pipeline-grails'
+ runtimeOnly 'org.fusesource.jansi:jansi'
+
+ integrationTestImplementation testFixtures('org.apache.grails:grails-geb')
+}
+
+apply {
+ from rootProject.layout.projectDirectory.file('gradle/functional-test-config.gradle')
+ from rootProject.layout.projectDirectory.file('gradle/test-webjar-asset-config.gradle')
+ from rootProject.layout.projectDirectory.file('gradle/grails-extension-gradle-config.gradle')
+}
diff --git a/grails-test-examples/jetty/grails-app/assets/javascripts/application.js b/grails-test-examples/jetty/grails-app/assets/javascripts/application.js
new file mode 100644
index 00000000000..7914e5e77f2
--- /dev/null
+++ b/grails-test-examples/jetty/grails-app/assets/javascripts/application.js
@@ -0,0 +1,16 @@
+// 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
+//
+// https://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.
+
+//= require_self
diff --git a/grails-test-examples/jetty/grails-app/assets/stylesheets/application.css b/grails-test-examples/jetty/grails-app/assets/stylesheets/application.css
new file mode 100644
index 00000000000..ad24325fbb9
--- /dev/null
+++ b/grails-test-examples/jetty/grails-app/assets/stylesheets/application.css
@@ -0,0 +1,18 @@
+/*
+ * 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
+ *
+ * https://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.
+ *
+ *= require_self
+ */
diff --git a/grails-test-examples/jetty/grails-app/conf/application.yml b/grails-test-examples/jetty/grails-app/conf/application.yml
new file mode 100644
index 00000000000..45c13725fda
--- /dev/null
+++ b/grails-test-examples/jetty/grails-app/conf/application.yml
@@ -0,0 +1,60 @@
+# 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
+#
+# https://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.
+
+---
+grails:
+ profile: web
+ codegen:
+ defaultPackage: issue12688
+info:
+ app:
+ name: '@info.app.name@'
+ version: '@info.app.version@'
+ grailsVersion: '@info.app.grailsVersion@'
+---
+grails:
+ mime:
+ types:
+ all: '*/*'
+ atom: application/atom+xml
+ css: text/css
+ csv: text/csv
+ form: application/x-www-form-urlencoded
+ html:
+ - text/html
+ - application/xhtml+xml
+ js: text/javascript
+ json:
+ - application/json
+ - text/json
+ multipartForm: multipart/form-data
+ pdf: application/pdf
+ rss: application/rss+xml
+ text: text/plain
+ hal:
+ - application/hal+json
+ - application/hal+xml
+ xml:
+ - text/xml
+ - application/xml
+ views:
+ gsp:
+ encoding: UTF-8
+ htmlcodec: xml
+ codecs:
+ expression: html
+ scriptlet: html
+ taglib: none
+ staticparts: none
diff --git a/grails-test-examples/jetty/grails-app/conf/logback-spring.xml b/grails-test-examples/jetty/grails-app/conf/logback-spring.xml
new file mode 100644
index 00000000000..489999587fb
--- /dev/null
+++ b/grails-test-examples/jetty/grails-app/conf/logback-spring.xml
@@ -0,0 +1,42 @@
+
+
+
${message}
+ + diff --git a/grails-test-examples/jetty/src/integration-test/groovy/issue12688/JettySessionSpec.groovy b/grails-test-examples/jetty/src/integration-test/groovy/issue12688/JettySessionSpec.groovy new file mode 100644 index 00000000000..afb614c12fb --- /dev/null +++ b/grails-test-examples/jetty/src/integration-test/groovy/issue12688/JettySessionSpec.groovy @@ -0,0 +1,51 @@ +/* + * 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 + * + * https://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. + */ + +package issue12688 + +import issue12688.pages.SessionFormPage +import issue12688.pages.SessionShowPage + +import grails.plugin.geb.ContainerGebSpec +import grails.testing.mixin.integration.Integration + +/** + * Regression test for https://github.com/apache/grails-core/issues/12688. + * + * Verifies that a Grails application running on Jetty (instead of Tomcat) can process + * request parameters and store values in the HTTP session without serialization errors. + * Jetty's session management checks serializability of session attributes, so this test + * confirms there are no NotSerializableException warnings from GrailsParameterMap. + */ +@Integration +class JettySessionSpec extends ContainerGebSpec { + + void 'request params can be processed and stored in session on a Jetty-backed Grails app'() { + given: 'a user visits the session form' + to(SessionFormPage) + + when: 'they submit a message value' + messageInput.value('hello jetty') + submitButton.click() + + then: 'the value is stored in session and displayed after the redirect' + at(SessionShowPage) + messageParagraph.text() == 'hello jetty' + } +} diff --git a/grails-test-examples/jetty/src/integration-test/groovy/issue12688/pages/SessionFormPage.groovy b/grails-test-examples/jetty/src/integration-test/groovy/issue12688/pages/SessionFormPage.groovy new file mode 100644 index 00000000000..23a5c4a5c6c --- /dev/null +++ b/grails-test-examples/jetty/src/integration-test/groovy/issue12688/pages/SessionFormPage.groovy @@ -0,0 +1,32 @@ +/* + * 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 + * + * https://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. + */ + +package issue12688.pages + +import geb.Page + +class SessionFormPage extends Page { + + static url = '/session' + static at = { title == 'Session Test' } + static content = { + messageInput { $('input#message') } + submitButton { $('input#submit') } + } +} diff --git a/grails-test-examples/jetty/src/integration-test/groovy/issue12688/pages/SessionShowPage.groovy b/grails-test-examples/jetty/src/integration-test/groovy/issue12688/pages/SessionShowPage.groovy new file mode 100644 index 00000000000..5c0f577cba5 --- /dev/null +++ b/grails-test-examples/jetty/src/integration-test/groovy/issue12688/pages/SessionShowPage.groovy @@ -0,0 +1,31 @@ +/* + * 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 + * + * https://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. + */ + +package issue12688.pages + +import geb.Page + +class SessionShowPage extends Page { + + static url = '/session/show' + static at = { title == 'Session Value' } + static content = { + messageParagraph { $('p#message') } + } +} diff --git a/settings.gradle b/settings.gradle index df1adbe0a0c..9e438a0d935 100644 --- a/settings.gradle +++ b/settings.gradle @@ -409,7 +409,8 @@ include( 'grails-test-examples-scaffolding', 'grails-test-examples-scaffolding-fields', 'grails-test-examples-views-functional-tests', - 'grails-test-examples-views-functional-tests-plugin' + 'grails-test-examples-views-functional-tests-plugin', + 'grails-test-examples-jetty' ) project(':grails-test-examples-async-events-pubsub-demo').projectDir = file('grails-test-examples/async-events-pubsub-demo') project(':grails-test-examples-app1').projectDir = file('grails-test-examples/app1') @@ -448,6 +449,7 @@ project(':grails-test-examples-scaffolding').projectDir = file('grails-test-exam project(':grails-test-examples-scaffolding-fields').projectDir = file('grails-test-examples/scaffolding-fields') project(':grails-test-examples-views-functional-tests').projectDir = file('grails-test-examples/views-functional-tests') project(':grails-test-examples-views-functional-tests-plugin').projectDir = file('grails-test-examples/views-functional-tests-plugin') +project(':grails-test-examples-jetty').projectDir = file('grails-test-examples/jetty') includeBuild('./grails-gradle') { name = 'grails-gradle'