You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by ja...@apache.org on 2025/06/25 14:51:03 UTC
(grails-static-website) 01/01: Implement redirect from grails.org to grails.apache.org via meta refresh tag
This is an automated email from the ASF dual-hosted git repository.
jamesfredley pushed a commit to branch meta-refresh-redirect-grails-org
in repository https://gitbox.apache.org/repos/asf/grails-static-website.git
commit c023f88ad2f3aacfe526cf3ff0978937b7e1a237
Author: James Fredley <ja...@users.noreply.github.com>
AuthorDate: Wed Jun 25 10:50:48 2025 -0400
Implement redirect from grails.org to grails.apache.org via meta refresh tag
---
api.html | 136 +-
blog/2015-03-01.html | 442 +-
blog/2016-04-01-1.html | 160 +-
blog/2016-04-01-2.html | 163 +-
blog/2016-04-13.html | 198 +-
blog/2016-04-27.html | 165 +-
blog/2016-04-28.html | 158 +-
blog/2016-05-26.html | 176 +-
blog/2016-05-28.html | 607 +-
blog/2016-05-31.html | 172 +-
blog/2016-06-02.html | 158 +-
blog/2016-06-07.html | 215 +-
blog/2016-06-26.html | 528 +-
blog/2016-07-06.html | 317 +-
blog/2016-07-22.html | 173 +-
blog/2016-08-01.html | 228 +-
blog/2016-08-31.html | 284 +-
blog/2016-09-12.html | 291 +-
blog/2016-09-28.html | 180 +-
blog/2016-10-03.html | 400 +-
blog/2016-11-01.html | 281 +-
blog/2016-11-10.html | 239 +-
blog/2016-11-14.html | 223 +-
blog/2016-12-14.html | 282 +-
blog/2017-01-20-1.html | 159 +-
blog/2017-01-20-2.html | 159 +-
blog/2017-01-20-3.html | 160 +-
blog/2017-01-20-4.html | 160 +-
blog/2017-03-27.html | 176 +-
blog/2017-04-02.html | 230 +-
blog/2017-04-12.html | 256 +-
blog/2017-05-09.html | 220 +-
blog/2017-06-27.html | 251 +-
blog/2017-06-28.html | 221 +-
blog/2017-07-12.html | 160 +-
blog/2017-07-26.html | 158 +-
blog/2017-10-30.html | 160 +-
blog/2017-11-09.html | 173 +-
blog/2017-11-21.html | 180 +-
blog/2017-11-30.html | 156 +-
blog/2017-12-05.html | 345 +-
blog/2018-02-08.html | 159 +-
blog/2018-02-09.html | 170 +-
blog/2018-03-02.html | 190 +-
blog/2018-03-06.html | 158 +-
blog/2018-03-09.html | 171 +-
blog/2018-04-05.html | 211 +-
blog/2018-04-06.html | 170 +-
blog/2018-05-18.html | 169 +-
blog/2018-05-24.html | 292 +-
blog/2018-06-15.html | 189 +-
blog/2018-06-22.html | 440 +-
blog/2018-08-22-1.html | 158 +-
blog/2018-08-22-2.html | 158 +-
blog/2018-09-23.html | 172 +-
blog/2018-10-02.html | 215 +-
blog/2018-10-12.html | 171 +-
blog/2019-01-07.html | 165 +-
blog/2019-01-30.html | 165 +-
blog/2019-02-19.html | 165 +-
blog/2019-03-27.html | 170 +-
blog/2019-05-24.html | 171 +-
blog/2019-05-30.html | 163 +-
blog/2019-06-18.html | 164 +-
blog/2019-07-11.html | 166 +-
blog/2019-08-27.html | 183 +-
blog/2019-12-20.html | 170 +-
blog/2020-09-10-grails-state-of-union.html | 199 +-
blog/2020-10-01-2gm-town-hall.html | 162 +-
blog/2020-10-16-2gm-town-hall-2020-q4.html | 170 +-
.../2020-10-26-grails-foundation-announcement.html | 155 +-
blog/2021-01-22-grails-exciting-updates.html | 194 +-
blog/2021-02-05-2gm-town-hall-q1.html | 164 +-
...2021-02-12-alerts-regarding-bintray-sunset.html | 168 +-
blog/2021-03-22-meet-the-new-mascot.html | 161 +-
...-07-publish-grails-plugin-to-maven-central.html | 489 +-
blog/2021-05-21-2gm-town-hall-q2.html | 162 +-
blog/2021-06-10-grails-wrapper-update.html | 175 +-
blog/2021-07-20-call-for-productivity-tips.html | 160 +-
blog/2021-08-12-grails-5-rc1-release.html | 181 +-
blog/2021-08-25-groovy-4-webinar.html | 153 +-
blog/2021-09-02-grails-deep-dive.html | 154 +-
.../2021-09-15-q3-town-hall-meeting-scheduled.html | 155 +-
blog/2021-09-17-groovy-4-webinar.html | 159 +-
blog/2021-09-24-q3-town-hall-meeting.html | 161 +-
blog/2021-10-08-developer-advocate-announced.html | 165 +-
blog/2021-10-11-grails-5-ga.html | 185 +-
blog/2021-11-11.html | 160 +-
blog/2021-11-23-db-migration-plugin-update.html | 181 +-
...-12-06-february-2022-training-announcement.html | 159 +-
blog/2021-12-14-log4j2-cve.html | 189 +-
blog/2021-12-15-grails-five-one.html | 188 +-
blog/2022-01-07-2gm-town-hall-q1.html | 161 +-
...nterprise-tools-and-infrastructure-partner.html | 158 +-
blog/2022-03-31-grails-spring-rce.html | 166 +-
...rains-new-tools-and-infrastructure-partner.html | 158 +-
blog/2022-07-18-rce-vulnerability.html | 189 +-
blog/2022-09-28-static-binding-bug.html | 186 +-
blog/2022-11-22-ss-plugin-auth-cve.html | 178 +-
blog/2023-02-08-repository-maint.html | 156 +-
blog/2023-03-15-grails-6-m2.html | 235 +-
...grails-foundation-joining-unity-foundation.html | 159 +-
blog/2023-03-29-grails-6-m2.html | 241 +-
blog/2023-05-27-grails-6-rc1.html | 205 +-
blog/2023-07-25-introducing-grails-6.html | 200 +-
blog/2023-08-03-introducing-new-grails-forge.html | 273 +-
...-introducing-grails-spring-security-core-6.html | 196 +-
blog/2023-09-11-the-new-grails-plugin-portal.html | 202 +-
blog/2023-11-14-introducing-grails-6_1_0.html | 272 +-
blog/2023-12-20-cve-data-binding-dos.html | 172 +-
blog/2024-06-07-grails-future.html | 188 +-
blog/2024-06-25-grails-seven-mvp.html | 159 +-
.../2024-10-01-grails-community-contributions.html | 164 +-
blog/2024-10-03-introducing-grails-6-2-1.html | 264 +-
blog/2024-11-20-introducing-grails-6-2-2.html | 261 +-
blog/2024-12-23-grails-7-m1.html | 404 +-
...25-01-02-grails-community-rockstar-fredley.html | 182 +-
blog/2025-01-03-introducing-grails-6-2-3.html | 208 +-
blog/2025-03-05-grails-7-m3.html | 434 +-
blog/index.html | 830 +--
blog/tag/4.html | 154 +-
blog/tag/angular.html | 139 +-
blog/tag/bintray.html | 139 +-
blog/tag/config.html | 133 +-
blog/tag/deployment.html | 145 +-
blog/tag/eclipse.html | 133 +-
blog/tag/foundation.html | 133 +-
blog/tag/geb.html | 133 +-
blog/tag/gorm.html | 163 +-
blog/tag/gradle.html | 139 +-
blog/tag/grails.html | 133 +-
blog/tag/graphql.html | 133 +-
blog/tag/groovy.html | 151 +-
blog/tag/groovy3.html | 133 +-
blog/tag/javascript.html | 139 +-
blog/tag/json.html | 139 +-
blog/tag/logback.html | 133 +-
blog/tag/logging.html | 133 +-
blog/tag/mascot.html | 133 +-
blog/tag/micronaut.html | 133 +-
blog/tag/monitoring.html | 133 +-
blog/tag/plugins.html | 163 +-
blog/tag/podcast.html | 133 +-
blog/tag/quickcast.html | 199 +-
blog/tag/react.html | 157 +-
blog/tag/release.html | 169 +-
blog/tag/rest.html | 139 +-
blog/tag/spock.html | 133 +-
blog/tag/ssl.html | 133 +-
blog/tag/townhall.html | 151 +-
blog/tag/travis.html | 133 +-
blog/tag/video.html | 133 +-
blog/tag/webinar.html | 217 +-
blog/tag/yourkit.html | 133 +-
buildstatus.html | 1290 +---
casestudies/boosting-agility-with-grails.html | 184 +-
...y-enterprise-scale-application-development.html | 206 +-
...rehensive-solution-for-a-public-university.html | 173 +-
.../grails-increases-developer-productivity.html | 204 +-
...ghput-and-delivery-performance-with-grails.html | 194 +-
casestudies/index.html | 154 +-
community-code-of-conduct.html | 234 +-
community-guidelines.html | 187 +-
community.html | 292 +-
documentation.html | 300 +-
download.html | 189 +-
ecosystem.html | 144 +-
events.html | 6 +-
faq.html | 180 +-
foundation/index.html | 185 +-
foundation/minutes/20210321-tab.html | 250 +-
foundation/minutes/20211217-tab.html | 292 +-
foundation/minutes/20220323-tab.html | 335 +-
foundation/minutes/20220711-tab.html | 243 +-
foundation/minutes/20221128-tab.html | 282 +-
foundation/minutes/index.html | 159 +-
foundation/sponsor-list.html | 193 +-
foundation/sponsorship.html | 890 +--
foundation/thank-you.html | 145 +-
gormApi.html | 7 +-
index.html | 248 +-
learn.html | 6 +-
learning.html | 266 +-
legacy-plugins.html | 130 +-
mailing-lists.html | 6 +-
plugins.html | 6373 +-------------------
plugins/owners/9ci.html | 1421 +----
plugins/owners/ZenHarbinger.html | 1358 +----
plugins/owners/agileorbit.html | 1352 +----
plugins/owners/agorapulse.html | 1622 +----
plugins/owners/ajay-kumar.html | 1355 +----
plugins/owners/amc-world.html | 1358 +----
plugins/owners/amitjain.html | 1355 +----
plugins/owners/andreperegrina.html | 1355 +----
plugins/owners/anthofo.html | 1361 +----
plugins/owners/appcela.html | 1355 +----
plugins/owners/ataylor284.html | 1355 +----
plugins/owners/benlucchesi.html | 1352 +----
plugins/owners/bertramlabs.html | 1642 +----
plugins/owners/bmuschko.html | 1355 +----
plugins/owners/bostanio.html | 1349 +----
plugins/owners/budjb.html | 1537 +----
plugins/owners/captivatelabs.html | 1358 +----
plugins/owners/carlosmtobon.html | 1358 +----
plugins/owners/cazacugmihai.html | 1355 +----
plugins/owners/cdrchops.html | 1355 +----
plugins/owners/charlieamat.html | 1358 +----
plugins/owners/craigburke.html | 1376 +----
plugins/owners/ctoestreich.html | 1459 +----
plugins/owners/cwang.html | 1343 +----
plugins/owners/danlobo.html | 1355 +----
plugins/owners/daraii.html | 1352 +----
plugins/owners/dbpatel219.html | 1349 +----
plugins/owners/desirable-objects.html | 1383 +----
plugins/owners/dmahapatro.html | 1373 +----
plugins/owners/domurtag.html | 1361 +----
plugins/owners/donald-jackson.html | 1358 +----
plugins/owners/double16.html | 1352 +----
plugins/owners/dpcasady.html | 1358 +----
plugins/owners/dtanner.html | 1352 +----
plugins/owners/dubems.html | 1355 +----
plugins/owners/enesakar.html | 1355 +----
plugins/owners/errbuddy.html | 1358 +----
plugins/owners/exanpe.html | 1355 +----
plugins/owners/frnktrgr.html | 1385 +----
plugins/owners/goodstartgenetics.html | 1355 +----
plugins/owners/gpc.html | 1466 +----
plugins/owners/grails-aws.html | 1355 +----
plugins/owners/grails-plugins.html | 1355 +----
plugins/owners/grails.html | 2595 +-------
plugins/owners/gregopet.html | 1348 +----
plugins/owners/groovyzk.html | 1361 +----
plugins/owners/herrvendil.html | 1349 +----
plugins/owners/iamthechad.html | 1352 +----
plugins/owners/ikalizpet.html | 1364 +----
plugins/owners/ishults.html | 1355 +----
plugins/owners/jamescookie.html | 1358 +----
plugins/owners/jeetmp3.html | 1355 +----
plugins/owners/jeffwils.html | 1361 +----
plugins/owners/junehasissues.html | 1355 +----
plugins/owners/jvilaplana.html | 1355 +----
plugins/owners/kaleidos.html | 1358 +----
plugins/owners/kensiprell.html | 1358 +----
plugins/owners/lduarte.html | 1361 +----
plugins/owners/lgrignon.html | 1358 +----
plugins/owners/longwa.html | 1355 +----
plugins/owners/mathifonseca.html | 1386 +----
plugins/owners/matrei.html | 1379 +----
plugins/owners/matrixcrawler.html | 1409 +----
plugins/owners/mkobel.html | 1349 +----
plugins/owners/moceanapi.html | 1352 +----
plugins/owners/modnsolutions.html | 1352 +----
plugins/owners/mrhaki.html | 1373 +----
plugins/owners/neilab.html | 1373 +----
plugins/owners/nerderg.html | 1368 +----
plugins/owners/nobeans.html | 1355 +----
plugins/owners/novadge.html | 1415 +----
plugins/owners/ondrej-kvasnovsky.html | 1355 +----
plugins/owners/orkonano.html | 1358 +----
plugins/owners/pankajtandon.html | 1355 +----
plugins/owners/piotrchowaniec.html | 1348 +----
plugins/owners/puneetbehl.html | 1379 +----
plugins/owners/puravida-software.html | 1344 +----
plugins/owners/purpleraven.html | 1413 +----
plugins/owners/reid.html | 1349 +----
plugins/owners/relaximus.html | 1361 +----
plugins/owners/rlovtangen.html | 1355 +----
plugins/owners/rpalcolea.html | 1406 +----
plugins/owners/rvanderwerf.html | 1358 +----
plugins/owners/sachinverma.html | 1373 +----
plugins/owners/salex772.html | 1364 +----
plugins/owners/saw303.html | 1367 +----
plugins/owners/sbglasius.html | 1388 +----
plugins/owners/sergiomichels.html | 1355 +----
plugins/owners/sheehan.html | 1361 +----
plugins/owners/snimavat.html | 1379 +----
plugins/owners/splix.html | 1361 +----
plugins/owners/stefanogualdi.html | 1355 +----
plugins/owners/symentis.html | 1358 +----
plugins/owners/tadodotcom.html | 1359 +----
plugins/owners/technipelago.html | 1355 +----
plugins/owners/tednaleid.html | 1349 +----
plugins/owners/tony75.html | 1349 +----
plugins/owners/tothenew.html | 1354 +----
plugins/owners/touk.html | 1358 +----
plugins/owners/troutbird.html | 1377 +----
plugins/owners/uberall.html | 1367 +----
plugins/owners/vahid.html | 1532 +----
plugins/owners/vahidhedayati.html | 1358 +----
plugins/owners/valentingoebel.html | 1361 +----
plugins/owners/virtualdogbert.html | 1388 +----
plugins/owners/vsachinv.html | 1354 +----
plugins/owners/yamkazu.html | 1355 +----
plugins/owners/yingliang-du.html | 1349 +----
plugins/owners/zacharyklein.html | 1364 +----
plugins/owners/zyro.html | 1355 +----
plugins/tags/acl.html | 1385 +----
plugins/tags/airbrake.html | 1349 +----
plugins/tags/ajax.html | 1361 +----
plugins/tags/alexa.html | 1358 +----
plugins/tags/amazon.html | 1403 +----
plugins/tags/angular-1.html | 1400 +----
plugins/tags/angular-2.html | 1349 +----
plugins/tags/antisamy.html | 1358 +----
plugins/tags/asset-pipeline.html | 1582 +----
plugins/tags/async.html | 1445 +----
plugins/tags/auditing.html | 1367 +----
plugins/tags/autocomplete.html | 1355 +----
plugins/tags/aws.html | 1568 +----
plugins/tags/babel.html | 1358 +----
plugins/tags/bootstrap.html | 1376 +----
plugins/tags/business-rules.html | 1367 +----
plugins/tags/cache.html | 1422 +----
plugins/tags/calendar.html | 1370 +----
plugins/tags/captcha.html | 1388 +----
plugins/tags/cas.html | 1361 +----
plugins/tags/cassandra.html | 1358 +----
plugins/tags/chat.html | 1358 +----
plugins/tags/ckeditor.html | 1355 +----
plugins/tags/client.html | 1361 +----
plugins/tags/cloud.html | 1355 +----
plugins/tags/cmeditor.html | 1352 +----
plugins/tags/codemirror.html | 1352 +----
plugins/tags/coffeescript.html | 1358 +----
plugins/tags/cognito.html | 1403 +----
plugins/tags/command-objects.html | 1358 +----
plugins/tags/compass.html | 1358 +----
plugins/tags/config.html | 1379 +----
plugins/tags/console.html | 1361 +----
plugins/tags/cookies.html | 1379 +----
plugins/tags/cors.html | 1376 +----
plugins/tags/csrf.html | 1358 +----
plugins/tags/css.html | 1406 +----
plugins/tags/csv.html | 1423 +----
plugins/tags/cxf.html | 1382 +----
plugins/tags/database.html | 1633 +----
plugins/tags/datatables.net.html | 1355 +----
plugins/tags/date.html | 1394 +----
plugins/tags/debugging.html | 1361 +----
plugins/tags/delete.html | 1355 +----
plugins/tags/dropwizard.html | 1376 +----
plugins/tags/dynamodb.html | 1403 +----
plugins/tags/ehcache.html | 1358 +----
plugins/tags/elasticsearch.html | 1352 +----
plugins/tags/ember.html | 1358 +----
plugins/tags/encryption.html | 1373 +----
plugins/tags/enums.html | 1358 +----
plugins/tags/envers.html | 1349 +----
plugins/tags/events.html | 1358 +----
plugins/tags/excel.html | 1412 +----
plugins/tags/export.html | 1391 +----
plugins/tags/facebook.html | 1379 +----
plugins/tags/file-viewer.html | 1354 +----
plugins/tags/file.html | 1361 +----
plugins/tags/filter.html | 1357 +----
plugins/tags/filterpane.html | 1357 +----
plugins/tags/flyway.html | 1352 +----
plugins/tags/fontawesome.html | 1358 +----
plugins/tags/forms.html | 1349 +----
plugins/tags/framework.html | 1361 +----
plugins/tags/geb.html | 1367 +----
plugins/tags/google.html | 1355 +----
plugins/tags/gorm.html | 1589 +----
plugins/tags/graph.html | 1355 +----
plugins/tags/graphite.html | 1355 +----
plugins/tags/graphql.html | 1361 +----
plugins/tags/gravatar.html | 1358 +----
plugins/tags/grooscript.html | 1355 +----
plugins/tags/groovy.html | 1355 +----
plugins/tags/handlebars.html | 1391 +----
plugins/tags/hazelcast.html | 1367 +----
plugins/tags/health-check.html | 1370 +----
plugins/tags/hibernate.html | 1466 +----
plugins/tags/html.html | 1367 +----
plugins/tags/http-client.html | 1373 +----
plugins/tags/http-session.html | 1385 +----
plugins/tags/https.html | 1358 +----
plugins/tags/i18n.html | 1394 +----
plugins/tags/icalendar.html | 1352 +----
plugins/tags/image.html | 1448 +----
plugins/tags/import.html | 1358 +----
plugins/tags/inertia.html | 1358 +----
plugins/tags/infobip.html | 1352 +----
plugins/tags/isomorphic.html | 1364 +----
plugins/tags/jasper.html | 1394 +----
plugins/tags/jasypt.html | 1373 +----
plugins/tags/java-date-time.html | 1355 +----
plugins/tags/javamelody.html | 1355 +----
plugins/tags/javascript.html | 1418 +----
plugins/tags/jax-rs.html | 1487 +----
plugins/tags/jedis.html | 1364 +----
plugins/tags/jenkins.html | 1358 +----
plugins/tags/jesque.html | 1382 +----
plugins/tags/jira.html | 1358 +----
plugins/tags/jms.html | 1358 +----
plugins/tags/json.html | 1494 +----
plugins/tags/kerberos.html | 1361 +----
plugins/tags/kineses.html | 1382 +----
plugins/tags/kinesis.html | 1358 +----
plugins/tags/kml.html | 1349 +----
plugins/tags/ldap.html | 1367 +----
plugins/tags/less.html | 1361 +----
plugins/tags/lightning.html | 1349 +----
plugins/tags/liquibase.html | 1361 +----
plugins/tags/liquid.html | 1358 +----
plugins/tags/lock.html | 1376 +----
plugins/tags/logging.html | 1406 +----
plugins/tags/logical-delete.html | 1358 +----
plugins/tags/mail.html | 1502 +----
plugins/tags/mailgun.html | 1358 +----
plugins/tags/mailhide.html | 1352 +----
plugins/tags/management.html | 1361 +----
plugins/tags/markdown.html | 1349 +----
plugins/tags/markup.html | 1358 +----
plugins/tags/memcached.html | 1373 +----
plugins/tags/messaging.html | 1402 +----
plugins/tags/metrics.html | 1376 +----
plugins/tags/micronaut.html | 1349 +----
plugins/tags/middleware.html | 1361 +----
plugins/tags/migration.html | 1409 +----
plugins/tags/moceanapi.html | 1352 +----
plugins/tags/mongodb.html | 1409 +----
plugins/tags/multitenant.html | 1354 +----
plugins/tags/mysql.html | 1355 +----
plugins/tags/neo4j.html | 1355 +----
plugins/tags/newrelic.html | 1355 +----
plugins/tags/nosql.html | 1361 +----
plugins/tags/oauth.html | 1355 +----
plugins/tags/oauth2.html | 1559 +----
plugins/tags/ods.html | 1370 +----
plugins/tags/owasp.html | 1361 +----
plugins/tags/p6spy.html | 1358 +----
plugins/tags/pagination.html | 1378 +----
plugins/tags/payment.html | 1397 +----
plugins/tags/paypal.html | 1379 +----
plugins/tags/pdf.html | 1412 +----
plugins/tags/permissions.html | 1367 +----
plugins/tags/postgres.html | 1361 +----
plugins/tags/postgresql.html | 1358 +----
plugins/tags/push-notification.html | 1352 +----
plugins/tags/pushover.html | 1352 +----
plugins/tags/qrcode.html | 1355 +----
plugins/tags/quartz.html | 1436 +----
plugins/tags/queue.html | 1403 +----
plugins/tags/rabbitmq.html | 1381 +----
plugins/tags/rdms.html | 1445 +----
plugins/tags/react.html | 1364 +----
plugins/tags/redis.html | 1427 +----
plugins/tags/rendering.html | 1361 +----
plugins/tags/reporting.html | 1403 +----
plugins/tags/reports.html | 1352 +----
plugins/tags/rest.html | 1411 +----
plugins/tags/retina.html | 1358 +----
plugins/tags/rxjava.html | 1403 +----
plugins/tags/rxjava2.html | 1358 +----
plugins/tags/s3.html | 1403 +----
plugins/tags/saml.html | 1385 +----
plugins/tags/sanitizer.html | 1358 +----
plugins/tags/sass.html | 1361 +----
plugins/tags/scaffolding.html | 1355 +----
plugins/tags/scheduling.html | 1460 +----
plugins/tags/scripting.html | 1355 +----
plugins/tags/scss.html | 1358 +----
plugins/tags/search.html | 1395 +----
plugins/tags/security.html | 2036 +------
plugins/tags/seed.html | 1355 +----
plugins/tags/segment.html | 1349 +----
plugins/tags/sendgrid.html | 1358 +----
plugins/tags/sentry.html | 1349 +----
plugins/tags/ses.html | 1403 +----
plugins/tags/shiro.html | 1382 +----
plugins/tags/slack.html | 1355 +----
plugins/tags/sms.html | 1388 +----
plugins/tags/sns.html | 1403 +----
plugins/tags/soap.html | 1397 +----
plugins/tags/spa.html | 1358 +----
plugins/tags/spring-boot-actuator.html | 1358 +----
plugins/tags/spring-security-rest.html | 1433 +----
plugins/tags/spring-security.html | 1961 +-----
plugins/tags/spring-ws.html | 1352 +----
plugins/tags/sqs.html | 1403 +----
plugins/tags/square.html | 1358 +----
plugins/tags/ssh.html | 1367 +----
plugins/tags/ssl.html | 1358 +----
plugins/tags/ssr.html | 1364 +----
plugins/tags/stripe.html | 1358 +----
plugins/tags/sts.html | 1403 +----
plugins/tags/swagger.html | 1376 +----
plugins/tags/testing.html | 1496 +----
plugins/tags/timezone.html | 1358 +----
plugins/tags/twilio.html | 1358 +----
plugins/tags/twitter.html | 1355 +----
plugins/tags/typescript.html | 1351 +----
plugins/tags/upload.html | 1400 +----
plugins/tags/util.html | 1355 +----
plugins/tags/vaadin.html | 1355 +----
plugins/tags/validation.html | 1406 +----
plugins/tags/views.html | 1451 +----
plugins/tags/websocket.html | 1376 +----
plugins/tags/xml.html | 1406 +----
plugins/tags/xss.html | 1361 +----
plugins/tags/zk-grails.html | 1361 +----
plugins/tags/zk.html | 1361 +----
privacy-policy.html | 452 +-
profiles.html | 190 +-
profiles/angular/index.html | 16 +-
profiles/angularjs/index.html | 16 +-
profiles/plugin/index.html | 16 +-
profiles/react-webpack/index.html | 16 +-
profiles/react/index.html | 16 +-
profiles/rest-api-plugin/index.html | 16 +-
profiles/rest-api/index.html | 16 +-
profiles/vue/index.html | 16 +-
profiles/web-plugin/index.html | 16 +-
profiles/web/index.html | 16 +-
profiles/webpack/index.html | 16 +-
search.html | 222 +-
single-page-documentation.html | 8 +-
sponsors.html | 8 +-
support.html | 159 +-
templates/plugins.html | 129 +-
trademark-policy.html | 207 +-
upgrade.html | 20 +-
usergroups.html | 6 +-
versioning.html | 8 +-
525 files changed, 2685 insertions(+), 482294 deletions(-)
diff --git a/api.html b/api.html
index 9d6aaf9e14..bef4d98586 100644
--- a/api.html
+++ b/api.html
@@ -1,128 +1,10 @@
<!DOCTYPE html>
-<html>
- <head>
- <meta name='google-site-verification' content='REYQ1_I6HGowAE7LOLVqfQbnKaB4IfFpMlGzMbJj55Q' />
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='icon' href='/images/favicon.ico' />
- <link rel='mask-icon' href='//images/grails-pinned-icon.svg' color='feb672' />
- <meta charset='UTF-8' />
- <title>Grails Framework</title>
- <link rel='stylesheet' href='/stylesheets/722163036.screen.css' />
- <script src='/javascripts/722163036.navigation.js'></script>
- </head>
- <body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='/images/grails_logo.svg' alt='Grails Logo'
- style="max-width: 8rem"/></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li>
- <a href='https://grails.org/learning.html'>Learning</a>
- </li>
- <li>
- <a href='https://grails.org/community.html'>Community</a>
- </li>
- <li>
- <a href='https://grails.org/search.html'>Search</a>
- </li>
-</ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li>
- <a href='https://grails.org/documentation.html'>Documentation</a>
- </li>
- <li>
- <a href='https://grails.org/download.html'>Download</a>
- </li>
- <li>
- <a href='https://plugins.grails.org'>Plugins</a>
- </li>
- <li>
- <a href='https://guides.grails.org/index.html'>Guides</a>
- </li>
- <li>
- <a href='https://grails.org/faq.html'>FAQ</a>
- </li>
- <li>
- <a href='https://grails.org/support.html'>Support</a>
- </li>
-</ul></nav>
- </div>
- </div>
-</header><iframe class='doc-embed' frameborder='0' height='100%' width='100%' style='display: block;padding-bottom: 70px;' src='https://docs.grails.org/latest/api/' /><footer>
- <div class='content'>
- <div class='ocihometograils'>
- <span>Sponsored by</span>
- <a href='https://objectcomputing.com/products/grails/'><img class='' src='/images/oci_home_to_grails.svg' alt='Object Computing - Home to Grails' width='300px' /></a>
- </div>
- <nav class='socialmedianav'><ul>
- <li>
- <a href='https://grails-slack.cfapps.io'><img class='' src='/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/watch?v=XnRNfDGkBVg&list=PLI74De5M9T73uH3WilDCePP2qfSDpMaGu'><img class='' src='/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/groups/39757'><img class='' src='/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li>
- <a href='https://twitter.com/grailsframework'><img class='' src='/images/twitter.svg' alt='Twitter Icon' /></a>
- </li>
-</ul></nav>
- <nav class='partnersnav'><ul>
- <li>Grails' repositories are hosted by
- <a href='http://artifactoryonline.com/'>Artifactory</a>
- </li>
- <li>Website hosting provided by
- <a href='http://run.pivotal.io/'>Pivotal</a>
- </li>
- <li>JetBrains supports Grails with its
- <a href='https://www.jetbrains.com/idea/'>IntelliJ IDEA IDE</a>
- </li>
- <li>YourKit supports Grails with its
- <a href='https://www.yourkit.com/java/profiler/index.jsp'>Java Profiler</a>
- </li>
- <li>Grails is Open Source
- <a href='http://www.apache.org/licenses/LICENSE-2.0.html'>Apache 2 License</a>
- </li>
- <li>
- <a href='https://grails.org/buildstatus.html'>Build Status</a>
- </li>
-</ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
-</script>
- <script type='text/javascript'>
-adroll_adv_id = "HBWJH4CQCJGS5DJRSB4Z4D";
-adroll_pix_id = "IVEQYFOZXZAPZMDVQH7BFE";
-/* OPTIONAL: provide email to improve user identification */
-/* adroll_email = "username@example.com"; */
-(function () {
- var _onload = function(){
- if (document.readyState && !/loaded|complete/.test(document.readyState)){setTimeout(_onload, 10);return}
- if (!window.__adroll_loaded){__adroll_loaded=true;setTimeout(_onload, 50);return}
- var scr = document.createElement("script");
- var host = (("https:" == document.location.protocol) ? "https://s.adroll.com" : "http://a.adroll.com");
- scr.setAttribute('async', 'true');
- scr.type = "text/javascript";
- scr.src = host + "/j/roundtrip.js";
- ((document.getElementsByTagName('head') || [null])[0] ||
- document.getElementsByTagName('script')[0].parentNode).appendChild(scr);
- };
- if (window.addEventListener) {window.addEventListener('load', _onload, false);}
- else {window.attachEvent('onload', _onload)}
-}());
-</script>
-</div></body>
-</html>
\ No newline at end of file
+<html lang="en">
+<head>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/api.html"/>
+</head>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/api.html">https://grails.apache.org/api.html</a></p>
+</body>
+</html>
diff --git a/blog/2015-03-01.html b/blog/2015-03-01.html
index 8fb8f3a9b1..01dca6e7a4 100644
--- a/blog/2015-03-01.html
+++ b/blog/2015-03-01.html
@@ -1,442 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Grails® 3 Interceptors</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Grails 3 interceptors are a great way to insert logic into the request handling process." />
- <meta name="date" content="March 1, 2015" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Grails 3 interceptors are a great way to insert logic into the request handling process.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Grails® 3 Interceptors'/>
- <meta property='og:description' content='Grails 3 interceptors are a great way to insert logic into the request handling process.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2015-03-01.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Grails® 3 Interceptors</h1>
-<p><span class="author">By Jeff Scott Brown</span></p>
-<p><span class="date">March 1, 2015</span></p>
-<h2>Introduction</h2>
-<p>Grails<sup>®</sup> 3 is a major step forward in the evolution of the framework and re-evaluates many aspects of the framework that have evolved over the years. One area of the framework that was re-evaluated is that related to Grails filters.</p>
-<p>Grails filters are a lot like servlet filters but are more simple and are better integrated into the Grails runtime and its conventions. Grails filters were a way to implement logic that might relate to any number of controllers and were a powerful and flexible way to address many of those concerns. Grails 3 introduces the notion of interceptors as a better way to address many of the types of concerns that previously would have been addressed with filters.</p>
-<p>Like filters, interceptors contain code which may be applied to requests before and/or after invoking controller actions without having to embed that logic into all of the controllers that the logic may relate to. Interceptors offer a number of benefits over filters including support for static compilation and more flexible configurability.</p>
-<h2>Defining An Interceptor</h2>
-<p>Like most Grails artifacts, interceptors are normal Groovy classes that follow certain conventions which allow the framework to identify them and augment them with a rich set of behavior that is relevant to tasks that interceptors frequently address.</p>
-<p>Because interceptors are often associated with controllers the convention is to define them under the <code>grails-app/controllers/</code> directory. Interceptor class names should end with the word <code>Interceptor</code>.</p>
-<pre><code class="language-groovy">// grails-app/controllers/demo/FirstInterceptor.groovy
-package demo
-
-class FirstInterceptor {
- // ...
-}
-</code></pre>
-<p>The interceptor class does noes not need to extend any special base class and does not need to be marked with any special annotations in order for the framework to recognize the class as an interceptor. The location of the source file and the name of the class are sufficient to register the class as an interceptor.</p>
-<p>The <code>create-interceptor</code> command may be used to define an interceptor.</p>
-<pre><code> $ grails create-interceptor demo.First
- | Created grails-app/controllers/demo/FirstInterceptor.groovy
- | Created src/test/groovy/demo/FirstInterceptorSpec.groovy
-</code></pre>
-<pre><code class="language-groovy">// grails-app/controllers/demo/FirstInterceptor.groovy
-package demo
-
-class FirstInterceptor {
-
- boolean before() { true }
-
- boolean after() { true }
-
- void afterView() {
- // no-op
- }
-
-}
-</code></pre>
-<pre><code class="language-groovy">// src/test/groovy/demo/FirstInterceptorSpec.groovy
-package demo
-
-
-import grails.test.mixin.TestFor
-import spock.lang.Specification
-
-@TestFor(FirstInterceptor)
-class FirstInterceptorSpec extends Specification {
-
- void "Test first interceptor matching"() {
- when:"A request matches the interceptor"
- withRequest(controller:"first")
-
- then:"The interceptor does match"
- interceptor.doesMatch()
- }
-}
-</code></pre>
-<h2>The Interceptor Trait</h2>
-<p>Grails 3 takes advantage of Groovy's powerful and flexible support for traits in many places. All interceptors are automatically made to implement the <a href="https://grails.org/doc/3.0.x/api/grails/artefact/Interceptor.html">grails.artefact.Interceptor</a> trait so all of the methods and properties defined by that trait and all of the methods and properties defined by traits which that trait extends are all available inside of an interceptor. This provides easy access to attributes [...]
-<h2>Matching Requests</h2>
-<p>A convention is imposed which will automatically configure interceptors to match all requests to their corresponding controller. The implicit mapping from an interceptor to a controller is based on the artifact names. For example, by default the <code>PersonInterceptor</code> will match all requests to the <code>PersonController</code>.</p>
-<p>Interceptors often need to deviate from the convention and define which requests they should participate in using the <code>match</code>or <code>matchAll</code> method.</p>
-<pre><code class="language-groovy">// grails-app/controllers/demo/FirstInterceptor.groovy
-package demo
-
-class FirstInterceptor {
-
- public FirstInterceptor() {
- // match all requests to the
- // reporting controller...
- match controller: 'reporting'
-
- // match a request to the create action
- // in the person controller
- match controller: 'person', action: 'create'
-
- // match all requests to the accounting
- // or payroll controller
- match controller: ~/(accounting|payroll)/
- }
-
- // ...
-}
-</code></pre>
-<p>The named arguments supported are <code>namespace</code>, <code>controller</code>, <code>action</code>, <code>method</code>, and <code>uri</code>. All of them except for <code>uri</code> accept either a <code>String</code> or a regex expression. The <code>uri</code> argument supports a <code>String</code> path that is compatible with Spring's <a href="https://docs.spring.io/spring/docs/4.1.7.RELEASE/javadoc-api/org/springframework/util/AntPathMatcher.html">org.springframework.util.Ant [...]
-<p>An interecptor may match all requests except requests that satisfy some condition.</p>
-<pre><code class="language-groovy">// grails-app/controllers/demo/FirstInterceptor.groovy
-package demo
-
-class FirstInterceptor {
-
- public FirstInterceptor() {
- // match all requests except requests
- // to the auth controller
- matchAll().excludes(controller: 'auth')
- }
-
- // ...
-}
-</code></pre>
-<p>The <code>match</code> and <code>matchAll</code> methods in an intereceptor each return an instance of <a href="https://grails.github.io/grails-doc/3.0.x/api/grails/interceptors/Matcher.html">grails.interceptors.Matcher</a>. Most of the methods in <code>Matcher</code> also return the <code>Matcher</code> which allows for method chaining as shown above with <code>matchAll().excludes(controller: 'auth')</code>.</p>
-<p>Care should be taken to narrow the group of requests that an interceptor is applied to. Keep in mind that whatever logic is contained in an interceptor is being engaged for all of the requests that the interceptor matches.</p>
-<h2>Interceptor Methods</h2>
-<p>There are 3 separate methods that an interceptor may define to participate in different parts of the request processing lifecycle. The <code>before</code> method is executed before the controller action is invoked. The <code>after</code> method is invoked after the controller action returns and before the view is rendered. The <code>afterView</code> method is invoked after the view is rendered. An interceptor may provide any combination of these 3 call back methods and does not need t [...]
-<p>The <code>before</code> and <code>after</code> methods have a <code>boolean</code> return type. The methods should return <code>true</code> to indicate that control should continue as usual without interruption. The methods should return <code>false</code> to indicate that the interceptor has decided that the request has been handled by the intereceptor and processing should not continue on as per usual. For example, a <code>before</code> interceptor may recognize that a request to a [...]
-<pre><code class="language-groovy">package demo
-
-class SimpleAuthInterceptor {
-
- public SimpleAuthInterceptor() {
- match controller: 'person'
- }
-
- boolean before() {
- // if the user has not been authenticated,
- // redirect to authenticate the user...
- if(!session.userHasBeenAuthenticated) {
- redirect controller: 'auth', action: 'login'
- return false
- }
- true
- }
-}
-</code></pre>
-<h2>Interceptor Ordering</h2>
-<p>Any number of interceptors may match a request and in some circumstances it may be useful to affect the order in which the interceptors are invoked. To support this, the framework will recognize an <code>int</code> property named <code>order</code> defined in any interceptor. The value of the <code>order</code> property may be any number. Intereceptors are sorted based on their order from lowest to highest value and executed in that order so an interceptor with an <code>order</code> o [...]
-<p>For convenience there are properties named <code>HIGHEST_PRECEDENCE</code> and <code>LOWEST_PRECEDENCE</code> which may be referenced when initializing the <code>order</code> property.</p>
-<pre><code class="language-groovy">package demo
-
-class FirstInterceptor {
-
- int order = HIGHEST_PRECEDENCE + 100
-
- // ...
-
-}
-</code></pre>
-<pre><code class="language-groovy">package demo
-
-class SecondInterceptor {
-
- int order = HIGHEST_PRECEDENCE + 200
-
- // ...
-
-}
-</code></pre>
-<h2>Static Compilation</h2>
-<p>Unlike Grails 2 filters, Grails 3 intercetors are compatible with Groovy's static compilation and as such may be marked with the <code>@CompileStatic</code> annotation. Static compilation may be of particular importance in an interceptor because code in an interceptor potentially could be executed as part of handling every request into the application so performance may be particularly important there. Referencing methods introduced by the <code>Interceptor</code> trait like <code>red [...]
-<h2>Logging</h2>
-<p>Like most Grails artifacts interceptors have a <code>log</code> property.</p>
-<pre><code class="language-groovy">package demo
-
-class SimpleAuthInterceptor {
-
- public SimpleAuthInterceptor() {
- match controller: 'person'
- }
-
- boolean before() {
- // if the user has not been authenticated,
- // redirect to authenticate the user...
- if(!session.userHasBeenAuthenticated) {
- // log a message
- log.debug 'Redirecting to login page'
- redirect controller: 'auth', action: 'login'
- return false
- }
- true
- }
-}
-</code></pre>
-<p>The default logger name for an interceptor is <code>grails.app.controllers</code>. For the interceptor shown above that would be <code>grails.app.controllers.demo.SimpleAuthInterceptor</code> so the logging could be configured in <code>grails-app/conf/logback.groovy</code> as shown below.</p>
-<pre><code class="language-groovy">// ...
-logger 'grails.app.controllers.demo.SimpleAuthInterceptor',
- DEBUG, ['STDOUT'], false
-</code></pre>
-<p>Note that the logger name prefix is <code>grails.app.controllers</code>, not <code>grails.app.interceptors</code>. This is because by default interceptors are defined under the <code>grails-app/controllers/</code> directory.</p>
-<p>The framework offers flexibility around this such that if you would like to separate your interceptors from your controllers you can do that by moving the interceptors to a directory like <code>grails-app/interceptors/</code>. If the interceptor defined above were moved from <code>grails-app/controllers/demo/SimpleAuthInterceptor.groovy</code> to <code>grails-app/interceptors/demo/SimpleAuthInterceptor.groovy</code>, the logger name would be <code>grails.app.interceptors.demo.SimpleAu [...]
-<h2>Interceptors Are Spring Beans</h2>
-<p>All interceptors are configured as beans in the Spring application context and are configured to be autowired by name. This means that just like other Grails artifacts, an interceptor may define a property with a name that matches a bean name and that property will be initialized using standard Spring dependency injection.</p>
-<p>In addition to participating in dependency injection, because interceptors are Spring beans they participate in all of the standard Spring bean management handling. For example, if an interceptor wanted access to the application's configuration, the intereceptor class could implement the <a href="https://grails.github.io/grails-doc/3.0.x/api/grails/core/support/GrailsConfigurationAware.html">grails.core.support.GrailsConfigurationAware</a> interface.</p>
-<pre><code class="language-groovy">package demo
-
-import grails.config.Config
-import grails.core.support.GrailsConfigurationAware
-
-class FirstInterceptor implements GrailsConfigurationAware {
-
- boolean before() {
- // ...
- }
-
- @Override
- void setConfiguration(Config co) {
- // configure the interceptor matching dynamically
- // based on what is in application.yml
- match co.'demo.interceptor.first'
- }
-}
-</code></pre>
-<p>With that in place, the request matching could be dynamically configured in <code>grails-app/conf/application.yml</code>.</p>
-<pre><code class="language-yml">demo:
- interceptor:
- first:
- action: save
- controller: person
-</code></pre>
-<h2>Testing Interceptors</h2>
-<p>Interceptors may be tested on their own as first class artifacts.</p>
-<pre><code class="language-groovy">// grails-app/controllers/demo/FirstInterceptor.groovy
-package demo
-
-class FirstInterceptor {
-
- public FirstInterceptor() {
- match controller: 'demo', action: 'index'
- }
-
- boolean before() {
- params.firstInterceptorRan = 'yes'
- true
- }
-}
-</code></pre>
-<pre><code class="language-groovy">// grails-app/controllers/demo/DemoController.groovy
-package demo
-
-class DemoController {
-
- def index() {
- render "firstInterceptorRan is ${params.firstInterceptorRan}"
- }
-
- def create() {
- render "firstInterceptorRan is ${params.firstInterceptorRan}"
- }
-}
-</code></pre>
-<pre><code class="language-groovy">// src/test/groovy/demo/DemoInterceptorSpec.groovy
-package demo
-
-
-import grails.test.mixin.TestFor
-import spock.lang.Specification
-
-@TestFor(DemoInterceptor)
-class DemoInterceptorSpec extends Specification {
-
- void "Test first interceptor matching"() {
- when:"A request is made to the index action"
- withRequest(controller:"demo", action: 'index')
-
- then:"The interceptor does match"
- interceptor.doesMatch()
- }
-
- void "Test first interceptor not matching"() {
- when:"A request is made to the create action"
- withRequest(controller:"demo", action: 'create')
-
- then:"The interceptor does not match"
- !interceptor.doesMatch()
- }
-}
-</code></pre>
-<p>The effects introduced by an interceptor may be tested in a functional test.</p>
-<pre><code class="language-groovy//">package demo
-
-import geb.spock.GebSpec
-import grails.test.mixin.integration.Integration
-
-@Integration
-class DemoControllerFunctionalSpec extends GebSpec {
-
- void "test the index action"() {
- when:
- go '/demo/index'
-
- then:
- $().text() == 'firstInterceptorRan is yes'
- }
-
- void "test the create action"() {
- when:
- go '/demo/create'
-
- then:
- $().text() == 'firstInterceptorRan is null'
- }
-}
-</code></pre>
-<h2>Conclusion</h2>
-<p>Grails 3 interceptors are a great way to insert logic into the request handling process. Like all Grails artifacts, interceptors take advantage of convention over configuration and sensible defaults to maximize flexibility and minimize configuration burden required to take advantage of really powerful functionality provided by the framework. Support for marking interceptors with <code>@CompileStatic</code> means that the performance cost associated with interceptor logic can be minimi [...]
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-03-introducing-grails-6-2-3.html'>
- <h3>January 3, 2025</h3>
- <h2>Introducing Grails Framework 6.2.3 Release</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-02-grails-community-rockstar-fredley.html'>
- <h3>January 2, 2025</h3>
- <h2>James Fredley Named 2025 Grails® Rock Star</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2015-03-01.html">https://grails.apache.org/blog/2015-03-01.html</a></p>
</body>
</html>
diff --git a/blog/2016-04-01-1.html b/blog/2016-04-01-1.html
index 7027eefe94..05149ffa14 100644
--- a/blog/2016-04-01-1.html
+++ b/blog/2016-04-01-1.html
@@ -1,160 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Quickcast #1: Grails® Interceptors</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Grails co-founder, Jeff Scott Brown, talks Grails interceptors." />
- <meta name="date" content="April 1, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='player'/><meta name='twitter:player' content='https://www.youtube.com/embed/XnRNfDGkBVg' />
-<meta name='twitter:player:width' content='560' />
-<meta name='twitter:player:height' content='315' />
-
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Grails co-founder, Jeff Scott Brown, talks Grails interceptors.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Quickcast #1: Grails® Interceptors'/>
- <meta property='og:description' content='Grails co-founder, Jeff Scott Brown, talks Grails interceptors.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-04-01-1.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Quickcast #1: Grails® Interceptors</h1>
-<p><span class="author">By Jeff Scott Brown</span></p>
-<p><span class="date">April 1, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a></p>
-<p>In this 17-minute video, the Grails<sup>®</sup> framework co-founder, <a href="https://objectcomputing.com/products/2gm-team#brown">Jeff Scott Brown</a>, talks Grails <a href="https://en.wikipedia.org/wiki/Interceptor_pattern">interceptors</a>.</p>
-<p>(Yes, <code>create-interceptor</code> actually creates an interceptor. Mind. Blown.)</p>
-<p>This tutorial assumes only basic familiarity with Groovy (which is pretty darned expressive anyway) and the MVC concept (which you already know). It also serves as an excellent introduction to the interceptor pattern in any language, because Grails' behind-the-scenes legwork lets you focus on the logic of the pattern.</p>
-<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
-<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/XnRNfDGkBVg" frameborder="0"></iframe>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2019-01-30.html'>
- <h3>January 30, 2019</h3>
- <h2>Quickcast #12: Building Grails® Applications ...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-1.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #10: Debugging Grails® Apps</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-2.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #11: Grails® Profiling with YourKit</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-04-01-1.html">https://grails.apache.org/blog/2016-04-01-1.html</a></p>
</body>
</html>
diff --git a/blog/2016-04-01-2.html b/blog/2016-04-01-2.html
index 1da9987234..ca952fe0b0 100644
--- a/blog/2016-04-01-2.html
+++ b/blog/2016-04-01-2.html
@@ -1,163 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Quickcast #2: JSON Views</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Jeff Scott Brown uses music examples to probe JSON views." />
- <meta name="date" content="April 1, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='player'/><meta name='twitter:player' content='https://www.youtube.com/embed/XnRNfDGkBVg' />
-<meta name='twitter:player:width' content='560' />
-<meta name='twitter:player:height' content='315' />
-
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Jeff Scott Brown uses music examples to probe JSON views.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Quickcast #2: JSON Views'/>
- <meta property='og:description' content='Jeff Scott Brown uses music examples to probe JSON views.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-04-01-2.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Quickcast #2: JSON Views</h1>
-<p><span class="author">By Jeff Scott Brown</span></p>
-<p><span class="date">April 1, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a> <a href="https://grails.org/blog/tag/json.html"><span class="hashtag">#json</span></a></p>
-<p>In a delightful and informative 15 minutes, the Grails<sup>®</sup> framework co-founder, <a href="https://objectcomputing.com/products/2gm-team#brown">Jeff Scott Brown</a>, probes JSON views.</p>
-<p>Beginning with a Grails 3.1.1 application created with a standard web profile, Jeff demonstrates how to add a few custom domain classes.</p>
-<p>Jeff uses music examples, including <em>Space Oddity</em> by David Bowie (RIP) and <em>Close to the Edge</em> by Yes, to populate an artist class with associated albums annotated with grails.rest.Resource.</p>
-<p>The goal is to publish a REST API under <code>/artists</code> to manage instances of the <code>artist</code> class and to support the JSON and XML formats. Sending a request to <code>/artists</code> delivers a list of artists, all of whom have albums associated with them.</p>
-<p>While the app is running in development mode, the JSON files can be altered, and the effects of those changes can be seen real-time in the application.</p>
-<p>This Quickcast assumes basic knowledge of Grails, JSON, and REST APIs.</p>
-<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
-<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/XnRNfDGkBVg" frameborder="0"></iframe>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2019-01-30.html'>
- <h3>January 30, 2019</h3>
- <h2>Quickcast #12: Building Grails® Applications ...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-1.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #10: Debugging Grails® Apps</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-2.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #11: Grails® Profiling with YourKit</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-04-01-2.html">https://grails.apache.org/blog/2016-04-01-2.html</a></p>
</body>
</html>
diff --git a/blog/2016-04-13.html b/blog/2016-04-13.html
index 1210d77966..9f2e8e69ac 100644
--- a/blog/2016-04-13.html
+++ b/blog/2016-04-13.html
@@ -1,198 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>JSON Views</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Learn about Grails Framework® convention-based content negotiation." />
- <meta name="date" content="April 13, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Learn about Grails Framework® convention-based content negotiation.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='JSON Views'/>
- <meta property='og:description' content='Learn about Grails Framework® convention-based content negotiation.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-04-13.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>JSON Views</h1>
-<p><span class="author">By Jeff Scott Brown</span></p>
-<p><span class="date">April 13, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/json.html"><span class="hashtag">#json</span></a> <a href="https://grails.org/blog/tag/rest.html"><span class="hashtag">#rest</span></a></p>
-<p>We recently published another Grails<sup>®</sup> Quickcast, brought to you in collaboration with DZone. In case you missed the first episode on Grails 3 Interceptors, you can view it <a href="https://objectcomputing.com/products/grails/resources/quickcasts/grails-interceptors">here</a>.</p>
-<p>The latest episode introduces JSON Views, a really simple yet powerful tool supported by Grails 3 for describing the JSON response formats for REST APIs. The video is available <a href="https://objectcomputing.com/products/grails/resources/quickcasts/json-views">here</a>.</p>
-<p>Another powerful feature supported by the tool is convention-based content negotiation.</p>
-<p>Consider a simple domain class.</p>
-<pre><code class="language-groovy">package demo
-
-import grails.rest.Resource
-
-@Resource(uri='/books', formats=['json'])
-class Book {
- String title
- String author
-}
-</code></pre>
-<p>A simple JSON view for that domain class might look like this.</p>
-<pre><code class="language-groovy">// grails-app/views/book/_book.gson
-import demo.Book
-
-model {
- Book book
-}
-
-json {
- bookTitle book.title
- bookAuthor book.author
-}
-</code></pre>
-<p>When a request is made to render a Book, that view will be used by default.</p>
-<pre><code> $ curl http://localhost:8080/books/1.json
- {"bookTitle":"Wool","bookAuthor":"Hugh Howey"}
-</code></pre>
-<p>Grails takes into account a number of factors when attempting to resolve the view including the content type, version and locale.</p>
-<p>The following paths are searched:</p>
-<ul>
-<li>view_name[_LOCALE][_ACCEPT_CONTENT_TYPE][_ACCEPT_VERSION].gson (Example: show_de_hal_v1.0.gson)</li>
-<li>view_name[_LOCALE][_ACCEPT_CONTENT_TYPE].gson (Example: show_de_hal.gson)</li>
-<li>view_name[_LOCALE][_ACCEPT_VERSION].gson (Example: show_de_v1.0.gson)</li>
-<li>view_name[_LOCALE].gson (Example: show_de.gson)</li>
-<li>view_name[_ACCEPT_CONTENT_TYPE][_ACCEPT_VERSION].gson (Example: show_hal_v1.0.gson)</li>
-<li>view_name[_ACCEPT_VERSION][_ACCEPT_CONTENT_TYPE].gson (Example: show_v1.0_hal.gson)</li>
-<li>view_name[_ACCEPT_CONTENT_TYPE].gson (Example: show_hal.gson)</li>
-<li>view_name[_ACCEPT_VERSION].gson (Example: show_v1.0.gson)</li>
-<li>view_name.gson (Example: show.gson)</li>
-</ul>
-<p>The content type (defined by either the <code>ACCEPT</code> header or file extension in the URI) is taken into account to allow different formats for the same view.</p>
-<p>For more detail, see <a href="https://grails.github.io/grails-views/latest/">the official documentation</a>.</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2017-01-20-2.html'>
- <h3>January 20, 2017</h3>
- <h2>Quickcast #4: Angular Scaffolding</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2016-04-01-2.html'>
- <h3>April 1, 2016</h3>
- <h2>Quickcast #2: JSON Views</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-04-13.html">https://grails.apache.org/blog/2016-04-13.html</a></p>
</body>
</html>
diff --git a/blog/2016-04-27.html b/blog/2016-04-27.html
index bc81c86590..6077649bdc 100644
--- a/blog/2016-04-27.html
+++ b/blog/2016-04-27.html
@@ -1,165 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>How to Use a Specific Version of GORM in Grails® 3</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Learn how you can enforce a particular GORM version in Grails 3." />
- <meta name="date" content="April 27, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Learn how you can enforce a particular GORM version in Grails 3.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='How to Use a Specific Version of GORM in Grails® 3'/>
- <meta property='og:description' content='Learn how you can enforce a particular GORM version in Grails 3.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-04-27.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>How to Use a Specific Version of GORM in Grails® 3</h1>
-<p><span class="author">By Graeme Rocher</span></p>
-<p><span class="date">April 27, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/gorm.html"><span class="hashtag">#gorm</span></a></p>
-<p>In order to ensure compatibility Grails<sup>®</sup> 3 ships with a BOM that applies dependency management and enforces a particular version of GORM when using Grails.</p>
-<p>Sometimes however, you want to use a different version or there is a more recent version of GORM out there that you would prefer to use.</p>
-<p>Luckily Gradle makes this fairly easy to control. Using the following snippet you can enforce a particular GORM version within your <code>build.gradle</code>:</p>
-<pre><code class="language-groovy">configurations.all {
- resolutionStrategy.eachDependency { DependencyResolveDetails details ->
- if (details.requested.group == 'org.grails'
- && details.requested.name.startsWith('grails-datastore')) {
- details.useVersion("5.0.5.RELEASE")
- }
- }
-}
-</code></pre>
-<p>In this example I’m forcing Gradle to resolve the <code>5.0.5.RELEASE</code> version of GORM using the Gradle resolutionStrategy.</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-10-02.jpg)'>
- <a href='https://grails.org/blog/2018-10-02.html'>
- <h3>October 2, 2018</h3>
- <h2>Grails® Domain Read-Only Attribute</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-04-05.jpg)'>
- <a href='https://grails.org/blog/2018-04-05.html'>
- <h3>April 5, 2018</h3>
- <h2>Introducing the Grails® 3 GORM Logical Delete...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-03-09.jpg)'>
- <a href='https://grails.org/blog/2018-03-09.html'>
- <h3>March 9, 2018</h3>
- <h2>Webinar: Build a Better API with GORM & Graph...</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-04-27.html">https://grails.apache.org/blog/2016-04-27.html</a></p>
</body>
</html>
diff --git a/blog/2016-04-28.html b/blog/2016-04-28.html
index 4ae5179161..6e7d80d0ec 100644
--- a/blog/2016-04-28.html
+++ b/blog/2016-04-28.html
@@ -1,158 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Grails® Slack Channel</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Connect with the core Grails development team in the Grails Slack channel." />
- <meta name="date" content="April 28, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Connect with the core Grails development team in the Grails Slack channel.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Grails® Slack Channel'/>
- <meta property='og:description' content='Connect with the core Grails development team in the Grails Slack channel.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-04-28.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Grails® Slack Channel</h1>
-<p><span class="author">By Jeff Scott Brown</span></p>
-<p><span class="date">April 28, 2016</span></p>
-<p>The folks at Slack describe their application as follows:</p>
-<blockquote>
-<p>A messaging app for teams who are changing the world.</p>
-</blockquote>
-<p>That sounds like us! :)</p>
-<p>We set up the Grails<sup>®</sup> Slack channel less than a year ago, and the channel has been very well received by the community. Our Slack channel is a great place to connect with the core Grails development team, as well as thousands of other Grails users, to ask and answer questions and to discuss ideas.</p>
-<p>The Grails Slack Channel can be found at <a href="https://grails.slack.com/">https://grails.slack.com</a>. Sign up at <a href="https://slack.grails.org">https://slack.grails.org</a>.</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-03-introducing-grails-6-2-3.html'>
- <h3>January 3, 2025</h3>
- <h2>Introducing Grails Framework 6.2.3 Release</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-02-grails-community-rockstar-fredley.html'>
- <h3>January 2, 2025</h3>
- <h2>James Fredley Named 2025 Grails® Rock Star</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-04-28.html">https://grails.apache.org/blog/2016-04-28.html</a></p>
</body>
</html>
diff --git a/blog/2016-05-26.html b/blog/2016-05-26.html
index 281b4ae7fa..fad2705168 100644
--- a/blog/2016-05-26.html
+++ b/blog/2016-05-26.html
@@ -1,176 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Deploying Grails® 3.1 Applications to JBoss 6.4 EAP</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Learn necessary configuration differences to deploy Grails 3.1 applications to JBoss 6.4 EAP" />
- <meta name="date" content="May 26, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Learn necessary configuration differences to deploy Grails 3.1 applications to JBoss 6.4 EAP'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Deploying Grails® 3.1 Applications to JBoss 6.4 EAP'/>
- <meta property='og:description' content='Learn necessary configuration differences to deploy Grails 3.1 applications to JBoss 6.4 EAP'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-05-26.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Deploying Grails® 3.1 Applications to JBoss 6.4 EAP</h1>
-<p><span class="author">By Graeme Rocher</span></p>
-<p><span class="date">May 26, 2016</span></p>
-<p>We had <a href="https://grails.io/post/142674392718/deploying-grails-3-to-wildfly-10">previously</a> described how to deploy Grails<sup>®</sup> 3.1 applications to WildFly 10, which is where all of the "cutting edge" work happens in the JBoss world.</p>
-<p>The process to deploy Grails 3.1 applications to JBoss 6.4 EAP is largely similar, with some minor configuration differences.</p>
-<p>Firstly, you have to configure your dependencies in <code>build.gradle</code> correctly by marking Tomcat as a provided dependency and including JAXB as a runtime dependency:</p>
-<pre><code class="language-groovy">provided "org.springframework.boot:spring-boot-starter-tomcat"
-runtime 'javax.xml.bind:jaxb-api:2.2.12'
-</code></pre>
-<p>Next you need to create a <code>src/main/webapp/WEB-INF/jboss-deployment-structure.xml</code> file with the following contents:</p>
-<pre><code class="language-xml"><?xml version='1.0' encoding='UTF-8'?>
-<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">
- <deployment>
- <exclusions>
- <module name="javaee.api"></module>
- <module name="javax.validation.api"></module>
- <module name="javax.faces.api"></module>
- <module name="org.hibernate.validator"></module>
- </exclusions>
- </deployment>
-</jboss-deployment-structure>
-</code></pre>
-<p>This will prevent JBoss from loading any APIs that conflict. For example Grails ships with <code>javax.validation</code> version 1.1 but JBoss 6.4 comes prepackages with version 1.0, so without this configuration you would end up with an exception such as:</p>
-<pre><code class="language-plaintext">Caused by: java.lang.NoSuchMethodError: javax.validation.spi.ConfigurationState.getParameterNameProvider()Ljavax/validation/ParameterNameProvider;
- at org.hibernate.validator.internal.engine.ValidatorFactoryImpl.<init>(ValidatorFactoryImpl.java:119)
- at org.hibernate.validator.HibernateValidator.buildValidatorFactory(HibernateValidator.java:45)
-</code></pre>
-<p>With these two changes in place you can run <code>gradle assemble</code> to produce a WAR file that can be deployed to JBoss 6.4 EAP!</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-03-introducing-grails-6-2-3.html'>
- <h3>January 3, 2025</h3>
- <h2>Introducing Grails Framework 6.2.3 Release</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-02-grails-community-rockstar-fredley.html'>
- <h3>January 2, 2025</h3>
- <h2>James Fredley Named 2025 Grails® Rock Star</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-05-26.html">https://grails.apache.org/blog/2016-05-26.html</a></p>
</body>
</html>
diff --git a/blog/2016-05-28.html b/blog/2016-05-28.html
index 6938268bfc..aa355c97ab 100644
--- a/blog/2016-05-28.html
+++ b/blog/2016-05-28.html
@@ -1,607 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Using React with the Grails® framework</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="React is a powerful and exciting library, and it’s a great choice for Grails® applications." />
- <meta name="date" content="May 28, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='React is a powerful and exciting library, and it’s a great choice for Grails® applications.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Using React with the Grails® framework'/>
- <meta property='og:description' content='React is a powerful and exciting library, and it’s a great choice for Grails® applications.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-05-28.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Using React with the Grails® framework</h1>
-<p><span class="author">By Zachary Klein</span></p>
-<p><span class="date">May 28, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/react.html"><span class="hashtag">#react</span></a> <a href="https://grails.org/blog/tag/javascript.html"><span class="hashtag">#javascript</span></a> <a href="https://grails.org/blog/tag/gradle.html"><span class="hashtag">#gradle</span></a></p>
-<p><strong>React</strong>, the JavaScript library from Facebook, has become a popular view technology for building dynamic, testable and performant user interfaces. While not a full-fledged framework like Angular or Ember, React’s focus on functional component-based views with no (or minimal) internal state makes it a great choice when building single page applications (SPA) or even dynamic subcomponents within a page-based application.</p>
-<p>Because it doesn't make assumptions about data-flow or controller logic outside of rendering the view, React relies on the developer to either provide these features directly in JavaScript or use another framework as a backend to support the React-based UI.</p>
-<p>It is this flexibility, in part, that makes React an appealing choice as a modern JavaScript view layer for <strong>Grails</strong><sup>®</sup> applications. Grails provides a robust backend built upon Spring Boot, GORM, and the Groovy programming language, as well as excellent support for generating restful endpoints that can be consumed by our React application. Since Grails 3 is also based upon Gradle, we can leverage <a href="https://github.com/srs/gradle-node-plugin">Gradle’s Nod [...]
-<p>Finally, <strong>JSX</strong> (React's XML-like syntax for defining components and page markup) is a powerful and flexible way to create dynamic views. In the author's opinion, creating components in JSX is quite analogous to defining custom GSP tags in a Grails taglib: a function which receives state via props (GSP <code>attrs</code>) and typically (but not always) renders markup based on that state. In React's case, these components are re-rendered upon every change to the app's sta [...]
-<p>In this article, we'll demonstrate how to integrate React into a Grails 3 application, using some of Grail’s restful features to get up and running quickly. We’ll spend a bit of time getting our project set up, and get to know some of the players in a React codebase.</p>
-<p>There are plenty of resources available to teach you React and restful API design, so I’m going to focus primarily on the “missing pieces” of combining React with a Grails application[1]. At the completion of this article, we'll list some resources to further your understanding of React. You'll be able to take this foundation and follow along with the same documentation, tutorials and other resources available to React developers.</p>
-<h2>Building Our Foundation</h2>
-<p>Let’s start with a brand new Grails 3.1.6 application, using the default web profile:</p>
-<pre><code> grails create-app com.ociweb.TodoList
-</code></pre>
-<p>Having run the <code>create-app</code> command, we already have a fully functioning backend application and server ready to go, and we can start up our app using the run-app command. View your new Grails application at <a href="http://localhost:8080/">http://localhost:8080</a>.</p>
-<p>Let’s create our data model.</p>
-<pre><code> grails create-domain-class com.ociweb.Todo
- grails create-domain-class com.ociweb.TodoList
-</code></pre>
-<pre><code class="language-groovy">//grails-app/domain/com/ociweb/Todo.groovy
- package com.ociweb
-
- class Todo {
-
- String name
-
- static belongsTo = [todoList: TodoList]
- }
-</code></pre>
-<pre><code class="language-groovy">//grails-app/domain/com/ociweb/TodoList.groovy
- package com.ociweb
-
- class TodoList {
-
- String name
-
- static hasMany = [ todos: Todo ]
-
- static constraints = {
- todos nullable: true
- }
- }
-</code></pre>
-<p>Now we have our domain model ready to go. By default Grails will provide us with an H2 database (in memory for development and test environments, as a file in production).</p>
-<p>Of course Grails supports all the major databases, including MySQL, Postgres, Oracle, and even NoSQL data stores like <strong>Mongo</strong>. Thanks to the flexibility of GORM, changing datasources is as simple as adding a couple dependencies or lines of configuration.</p>
-<p>Let’s switch to Mongo for this demonstration (this step is optional).</p>
-<p>Specify the mongo plugin in your <code>build.gradle</code> file:</p>
-<pre><code class="language-groovy">//build.gradle
-
- buildscript {
- //…
- dependencies {
- //…
- classpath "org.grails.plugins:hibernate4:5.0.0.BUILD-SNAPSHOT"
-
- dependencies {
- //…
- compile "org.grails.plugins:mongodb:5.0.0.BUILD-SNAPSHOT"
- compile "org.grails.plugins:hibernate4:5.0.0.BUILD-SNAPSHOT"
-</code></pre>
-<p>Now in our domain classes, add this static property to store the domain object in mongo:</p>
-<pre><code class="language-groovy"> //grail-app/domain/com/ociweb/Todo.groovy & TodoList.groovy
-
-//...
- static mapWith="mongo"
-</code></pre>
-<p>The plugin assumes you have mongodb installed and that mongod is running at port 27017; you can configure these to match your environment (<a href="https://gorm.grails.org/latest/mongodb/manual/index.html">see the plugin documentation for details</a>).</p>
-<h2>Defining Our API</h2>
-<p>Finally, we need to define a restful API for our React application.</p>
-<p>API design is a broad subject and not in scope of this article. However, Grails gives us a jumpstart to getting our API off the ground, providing endpoints for standard CRUD operations with minimal configuration. This is done by declaring our domain classes as resources, either by marking with the <code>@Resource</code> annotation or specifying the resource class within our URLMappings.</p>
-<p>Let's use the <code>@Resource</code> annotation for this example.</p>
-<pre><code class="language-groovy">//grails-app/domain/com/ociweb/Todo.groovy
- import grails.rest.Resource
-
- @Resource(uri='/api/todos', formats=['json'])
- class Todo {
- //...
-</code></pre>
-<pre><code class="language-groovy">//grails-app/domain/com/ociweb/TodoList.groovy
-
- @Resource(uri='/api/todoList', formats=['json'])
- class TodoList {
- //...
-</code></pre>
-<p>Note that we specify the content-type we wish to expose - we’ll use JSON.</p>
-<p>Finally, let’s add some initial data in <code>Bootstrap.groovy</code>:</p>
-<pre><code class="language-groovy">//grails-app/init/BootStrap.groovy
-
- import com.ociweb.*
-
- class BootStrap {
-
- def init = { servletContext ->
-
- if(!Todo.list()) {
- log.info "Creating todos..."
- def todoList = new TodoList(name: "Bob's List").save()
-
- [[name: "Task 1", todoList: todoList],
- [name: "Task 2", todoList: todoList],
- [name: "Task 3", todoList: todoList]].each { props ->
- def todo = new Todo()
- todo.properties = props
- todo.save(flush: true)
- }
-
- }
- }
- def destroy = {
- }
- }
-</code></pre>
-<p>Restart the application to load the new data.</p>
-<p>Now using a rest client application or a command-line utility like cURL, we can test drive our new API.</p>
-<pre><code> ~ curl -i -H "Accept: application/json" localhost:8080/api/todos
-
- HTTP/1.1 200 OK
- Server: Apache-Coyote/1.1
- X-Application-Context: application:development
- Content-Type: application/json;charset=UTF-8
- Transfer-Encoding: chunked
- Date: Sun, 15 May 2016 06:03:56 GMT
-
- [{"id":1,"list":{"id":1},"name":"Task 1"},{"id":2,"list":{"id":1},"name":"Task 2"},
- {"id":3,"list":{"id":1},"name":"Task 3"}]
-</code></pre>
-<pre><code> ~ curl -i -H "Accept: application/json" localhost:8080/api/todoList/1
-
- HTTP/1.1 200 OK
- Server: Apache-Coyote/1.1
- X-Application-Context: application:development
- Content-Type: application/json;charset=UTF-8
- Transfer-Encoding: chunked
- Date: Sun, 15 May 2016 06:06:00 GMT
-
- {"id":1,"name":"Bob's List","todos":[{"id":3},{"id":1},{"id":2}]
- }
-</code></pre>
-<p>There you go, we have a fully functioning restful API, backed by Mongo, and my coffee isn’t even cold yet.</p>
-<p>Now that we have our backend largely ready to go, we’re ready to set up React.</p>
-<blockquote>
-<p>Question: Why Do This?</p>
-<p>Why not use separate backend and front-end apps? In a microservice architecture, the work we’ve done might be sufficient - we could now build a separate React/node-based front-end application independent of our Grails backend. This is a great strategy, and <a href="https://docs.grails.org/latest/guide/single.html#webApiAndAngularProfiles">Grails 3.1 ships with a profile</a> tailored to this use case (web-api). Another option is to take advantage of Gradle multi-project builds, with se [...]
-<p>In this article, however, we’re considering the use of React as the “view” (the V in MVC) in a standard Grails application. And although we’re sharing a project directory, the React code and Grails artifacts are independent, and will communicate at runtime via our restful API just as if they were separate apps. The only thing tying these two apps together is the same Gradle build, which gives us the benefits described earlier in the article (in fact, it would be quite easy to split ou [...]
-<p>There’s many situations where a team may want to bring React into a Grails application, and it can be done in a way that allows for full developer productivity for both Grails and Node/React developers. Read on to see how!</p>
-</blockquote>
-<h2>Upgrading Our Build</h2>
-<p>React is most commonly used in combination with <a href="https://nodejs.org/">node.js</a>, and even if you aren’t intending to use node in particular, it still makes sense to have it installed if you intend to do any serious work with a Javascript library like React.</p>
-<p>The reason? You will use <code>npm</code> (which most surely <a href="https://www.quora.com/I-keep-hearing-NPM-doesnt-stand-for-Node-Package-Manager-what-does-it-stand-for">does <em>not</em> stand for Node Package Manager</a>) to download and install React and any other libraries you choose to use alongside it. <code>npm</code> can also be used to run scripts to build and test your React code, and it is the “handle” that will allow us to integrate our React code with our Gradle-based [...]
-<p>Once we have our React application set up, it will <em>not</em> be necessary for all developers to run node on their machines – we’ll take care of making that happen seamlessly as part of the Gradle build. However, any developer who is set up with node will be able to use <code>npm</code> and other node tools just as if they were working within a “plain” node application. This gives us the best of both worlds: Backend Grails developers can do their work without relying upon node and < [...]
-<p>In addition to installing node in your development environment, we will need to install the <a href="https://github.com/srs/gradle-node-plugin">gradle-node plugin</a> in our Grails application. This plugin will be the key to managing our <code>npm</code> tasks without relying upon local installations of node. Install the plugin by adding the plugin in <code>build.gradle</code>:</p>
-<pre><code class="language-groovy"> //build.gradle
-
- plugins {
- id "com.moowork.node" version "0.12"
- }
-
- node {
- version = '5.10.1'
- npmVersion = '3.8.3'
- distBaseUrl = 'https://nodejs.org/dist'
- download = true
- }
-</code></pre>
-<h2>Setting Up Our React Environment</h2>
-<p>For the next few steps, we'll use a local installation of <code>npm</code>. If you don't have it installed yet, I <em>highly</em> recommend <a href="https://github.com/creationix/nvm">nvm</a> to simplify installation and managing of node versions (if you've used <code>gvm</code>/<code>sdkman</code> for managing Grails/Groovy/Gradle versions, you'll like <code>nvm</code>). We'll be using the latest version of node 5.x as of the time of writing, which is 5.10.1. Please refer to <a href= [...]
-<p>Assuming you've installed <code>npm</code>, let's initialize our project. Run this command from your Grails project directory - you can accept the defaults for now; it's easy to fill in the details later):</p>
-<pre><code> npm init
-</code></pre>
-<p>Now we’re ready to install React and other dependencies.</p>
-<pre><code> npm install react react-dom --save
-
- npm install babel-core babel-preset-es2015 babel-preset-react babel-loader webpack --save-dev
-</code></pre>
-<p>There are plenty of options when setting up a React application, but these are the basics.</p>
-<p>Of course we need React and ReactDOM to render our app in the browser (React can also be used natively on mobile platforms like iOS, using <a href="https://facebook.github.io/react-native/">ReactNative</a> instead of ReactDOM).</p>
-<p>In addition, because we’ll be using JSX to write our components, we’ll need to use a <strong>transpiler</strong> to convert our React code into “plain vanilla” Javascript. Modern Javascript frameworks are moving much faster than web browsers, and many of the Javascript APIs commonly used in React projects are not yet standard in browsers.</p>
-<p><a href="https://babeljs.io/">babel</a> is a popular transpiler with many “presets” supporting different versions of Javascript syntax.</p>
-<p>To enable these presets, create a <code>.babelrc</code> file in the project root directory with this content:</p>
-<pre><code class="language-javascript"> {
- "presets": [
- "react",
- "es2015"
- ]
- }
-</code></pre>
-<p>This will ensure that babel uses the presets we’ve installed when transpiling our code.</p>
-<p>Of course, if we’re going to run our code through a transpiler, that means we need a build step to do the work. Typically in Grails applications, the asset pipeline plugin is the tool of choice for processing static assets like Javascript files. While there is a <a href="https://github.com/errbuddy/babel-asset-pipeline">Babel plugin</a> for the Grails asset pipeline, we are going to take a different approach and use **webpack **for this purpose; this will give us more flexibility in p [...]
-<h2>Webpack</h2>
-<p><a href="https://webpack.github.io" title="Webpack on GitHub">Webpack</a> represents a family of tools called “bundlers” and is a very popular choice for building React applications. It’s also a powerful and complex tool, but we can get started with a fairly minimal configuration.</p>
-<p>Here’s the big picture: Webpack will be responsible for running our React code through “loaders” for processing, and then output the finished product as a “bundle”. There are <a href="https://webpack.js.org/loaders/">loaders for nearly every conceivable asset type</a> you may want to access in your React application, including LESS, SASS, markdown, images, urls, generic files, and even Java properties files (such as <code>i18n/messages.properties</code> files). In our case, the babel- [...]
-<p>Here's our <code>webpack.config.js</code> file:</p>
-<pre><code class="language-javascript"> var path = require('path');
-
- module.exports = {
- entry: {
- index: './src/main/js/index.js'
- },
- output: {
- path: './grails-app/assets/javascripts',
- publicPath: '/assets/',
- filename: 'bundle.js'
- },
- module: {
- loaders: [
- {
- test: /\.js$/,
- include: path.join(__dirname, 'src/main/js'),
- loader: 'babel',
- query: {
- presets: ['es2015', 'react']
- }
- }
- ]
- }
- };
-</code></pre>
-<p>Don't be intimidated by this configuration; it’s actually fairly simple. The syntax is plain Javascript, which can be a bit confusing for a Grails developer accustomed to a DSL for config. The key points are that we’re defining where to find our React source files (<code>src/main/js/index.js</code>), where to output them (<code>grails-app/assets/javascripts</code>), and how to process them via the babel loader. You can learn more about configuring webpack <a href="https://webpack.js.o [...]
-<blockquote>
-<p>Where Is <code>/src/main/js</code>?</p>
-<p>Typically in a Grails application, Javascript files, like other static assets, live in the <code>grails-app/assets/</code> directory, which is where the asset pipeline picks them up. However, it is far more typical in a React application to keep the source files separate from the distributed bundle within a <code>src</code> directory, which makes sense, given that they contain “source code” for an application and are not really “assets” in the sense that Twitter Bootstrap or jQuery mi [...]
-<p>In addition, we will want to write tests for our React code, and it really doesn't make sense for tests to live in an “assets” directory structure. This is simply a matter of preference; in this article, we will store our React source code under <code>src/main/js</code> (in keeping with Grails' conventional <code>src/main/java</code> and <code>src/main/groovy</code> source structure), and our tests under <code>src/test/js</code>. These directories won’t exist by default, so we’ll need [...]
-</blockquote>
-<p>We will also want to add a couple of “scripts” to our <code>package.json</code> file in order to run webpack via <code>npm</code> (and later automate these with Gradle). In the <code>scripts</code> section, add these two lines:</p>
-<pre><code class="language-javascript"> "scripts": {
- "watch": "webpack --watch --colors --progress",
- "bundle": "webpack",
-</code></pre>
-<p>Now we can call these scripts using <code>npm</code>. Why do we have two scripts that both run webpack? The “bundle” version runs webpack and generates the bundle once (analogous to <code>grails war</code>), while the “watch” version will run webpack in “watch” mode, where the tool will automatically regenerate the bundle every time it detects a change to the source files (similar to <code>grails run-app</code>, with reloading of changed classes). We also enable some pretty formatting [...]
-<p>You can now run these scripts like so:</p>
-<pre><code> npm run bundle
-</code></pre>
-<p>However, you'll likely get an error saying "Entry module could not be found."</p>
-<p>Yep, we haven't added the "entry" file we specified earlier in our <code>src/main/js</code> directory yet. Let's do that.</p>
-<p>Create <code>index.js</code> and add a simple <code>alert()</code> statement:</p>
-<pre><code class="language-javascript">//src/main/js/index.js
- alert('Hello!');
-</code></pre>
-<p>Now if you run <code>npm run bundle</code>, you’ll get output like this:</p>
-<pre><code class="language-javascript"> Hash: bc17d737c7738edc00a5
- Version: webpack 1.13.0
- Time: 727ms
- Asset Size Chunks Chunk Names
- bundle.js 1.43 kB 0 [emitted] index
- + 1 hidden modules
-</code></pre>
-<p>And if you check your <code>grails-app/assets/javascripts</code> directory, you should see your shiny new <code>bundle.js</code>!</p>
-<p>Finally we need to load this bundle on our page. We’ll use a Grails controller and GSP view in this demonstration, but this could easily be a plain HTML page as well. Create a new controller <code>AppController</code>, and create an <code>index.gsp</code> page in the <code>grails-app/views/app</code> directory with this content:</p>
-<pre><code> grails create-controller com.ociweb.AppController
-</code></pre>
-<pre><code class="language-groovy">//grail-app/views/index.gsp
- <!doctype html>
- <html>
- <head>
- <title>Todo List</title>
- </head>
- <body>
- <div id="app"></div>
- <asset:javascript src="bundle.js" ></asset:javascript>
- </body>
- </html>
-</code></pre>
-<p>(Note that if we had used a plain HTML page, we would not be able to use the tag)</p>
-<p>Browse to <a href="http://localhost:8080/app"><code>http://localhost:8080/app</code></a>, and you should see your <code>alert()</code> statement.</p>
-<blockquote>
-<p>webpack-dev-server</p>
-<p>Webpack also includes a simple server called <em>webpack-dev-server</em>, which will operate similarly to “watch” mode but is actually able to instantly reload the bundle/s on your page, so that you can see your app update when you save your source file <a href="https://gaearon.github.io/react-hot-loader/getstarted/">without refreshing the browser</a>. This is a powerful feature, but it can be tricky to set up and is outside the scope of this article. I’ve created <a href="https://git [...]
-</blockquote>
-<h2>Enter Gradle</h2>
-<p>We’re almost done with our setup steps. With our current configuration, we can bundle our React code and output it to the asset pipeline, so the Grails app can serve it to our views. We also have a restful backend provided by our Grails app. Now we just need to make use of the Gradle node plugin [3] to automate the webpack bundling process when we 1. start the Grails app, and 2. package the Grails app as a WAR or JAR file.</p>
-<p>Add these two lines to the end of your <code>build.gradle</code>:</p>
-<pre><code class="language-groovy">//build.gradle
-
- processResources.dependsOn(['npmInstall', 'npm_run_bundle'])
-
- assetCompile.dependsOn(['npmInstall', 'npm_run_bundle'])
-</code></pre>
-<p>And that’s it! All we’ve done here is “hooked” a pair of <code>npm</code> tasks into our Gradle build process.</p>
-<p>The first is <code>npmInstall</code>, which is the equivalent of <code>npm install</code>, and is typically the first command you’d run when setting up an existing node-based project. <code>npm install</code> will read the <code>package.json</code> file and install any missing dependencies in your development environment.</p>
-<p>The second task should look familiar – it’s our <code>bundle</code> script we just used a moment ago. The Gradle node plugin supports this syntax for <em>any</em> script that you would normally run with <code>npm</code>. So any custom scripts you write in the future can be called via <code>npm_run_[your new script]</code>.</p>
-<p>Of course, you can run these scripts yourself through Gradle, using the included Gradle wrapper:</p>
-<pre><code> ./gradlew npm_run_watch
-</code></pre>
-<p>Other than the delay from spinning up Gradle, this will have the same effect as running <code>npm run watch</code> directly. This also means that developers without node installed can run these tasks without adding anything to their build environment - Gradle will handle those details seamlessly and OS-independently.</p>
-<p>When developing with React, typically you will run the Grails app <em>and</em> run webpack in “watch” mode, using <code>npm</code> or Gradle. As you make changes to your Javascript sources, webpack will automatically regenerate the <code>bundle.js</code>, and you can load the changes by refreshing your page.</p>
-<p><img src="2016-05-28-img01.png" alt="" />
-<em>Development Workflow with Grails & Webpack (<code>grails run-app</code> in the left terminal; <code>./gradlew npm_run_watch</code> in the right)</em></p>
-<p>Returning to our new <code>build.gradle</code> steps, you'll notice that we've attached these tasks to Grails' <code>processResources</code> (which runs every time the Grails app is started) and <code>assetCompile</code> (which runs when the app is packaged) tasks as dependencies. In this case, we just want to make sure the bundle is generated when the app is run, and when we build our WAR/JAR file, so that we’re always using our latest <code>bundle.js</code>. This also means you can [...]
-<p>Now you can build your Grails application on a Continuous Integration server that knows nothing about node or React. Gradle will handle installing node (local to the project), downloading <code>npm</code> dependencies, and running scripts like our webpack bundle, all without any changes to your build and deployment process.</p>
-<h2>Defining our Components</h2>
-<p>As we mentioned in the introduction to this article, React provides an <a href="https://facebook.github.io/react/docs/jsx-in-depth.html">expressive XML-like syntax</a> for defining our components. Let’s take a look at a simple JSX component that will render a Todo instance.</p>
-<pre><code class="language-javascript"> // /src/main/js/todo.js
-
- import React from 'react';
-
- function Todo(props) {
-
- const todo = props.todo;
-
- return(
- <li>
- <input id={ todo.id } type="checkbox"
- checked={ todo.complete ? 'checked' : '' }
- onChange={ props.toggleComplete } />
- <span>{ todo.name }</span>
- </li>
- );
- }
-</code></pre>
-<p>Again, this is not an in depth explanation of React and JSX, but you can learn a lot from a simple example like this one. As you can see, our component is a simple Javascript function, which takes an object (key/value pairs, similar to a Groovy map) that contains all attributes that are passed into this component.</p>
-<p>To use our new component, we just need to render it to our page (note that we have implemented a <code>toggleComplete</code>function yet, so we’re skipping that property for now - our component will still render but it won’t do anything yet):</p>
-<pre><code class="language-javascript"> // /src/main/js/index.js
-
- import React from 'react';
- import ReactDOM from 'react-dom';
- import Todo from './todo';
-
- //Call to render our component into the DOM…
- ReactDOM.render(
- <div>
-
- <h1>Our first Todo!</h1>
-{% raw %}
- <Todo todo={{name: 'Task 1', id: 1, complete: false}}></Todo>
-{% endraw %}
- </div>, document.getElementById('app')); // ...into this element on the page
-</code></pre>
-<p>Compare this to a custom GSP tag that might render similar output server-side:</p>
-<pre><code class="language-groovy"> //Hypothetical GSP taglib
-
- def todo = { attrs ->
-
- def todo = attrs.todo
-
- out << """
- <li>
- <input type="checkbox"
- checked=${todo.complete ? 'checked' : ''}
- onchange=${ /* specify an Ajax function */} />
- <span>${todo.name}</span>
- </li>
- """
- }
-
- <g:todo todo=${todo} ></g:todo>
-</code></pre>
-<p>Of course this is not an entirely fair comparison. <a href="https://objectcomputing.com/resources/publications/sett/december-2015-custom-gsp-tags-grails-best-kept-secret/">GSP tags provide much more functionality</a> than simply rendering of attributes, but Grails developers should find the syntax of JSX to be quite friendly and understandable coming from GSPs.</p>
-<p>JSX allows us to write Javascript expressions bound by curly braces, supports namespacing of components, and can make large, complex UIs easier to visualize while coding [4]. However, JSX is optional. You can write React components entirely in plain Javascript, but the resulting code is more verbose.</p>
-<blockquote>
-<p>Word of Warning</p>
-<p>This article is not intended as a comprehensive introduction to React. For developers new to Javascript, there are plenty of pitfalls to be had when learning this library. Understanding function context, "binding" [5], and passing functional callbacks into child components are key skills when writing clean code in React. These concepts are not React-specific – they are in fact plain Javascript – but they can be confusing to Groovy and Java programmers. There are many resourc [...]
-</blockquote>
-<h2>Calling the API</h2>
-<p>Now that we have our React app integrated into our Grails project and served up via the asset pipeline, we can start to build out our application and write components that consume our restful API. Because React is a view library, it doesn’t offer specialized features for communicating with a restful API. Developers are encouraged to use native Javascript APIs or other libraries to supply this functionality. The example project from this article uses the <a href="https://developer.mozi [...]
-<p>The app allows a user to create new todo lists and add new todo items to them. All changes are saved to the mongo database. It also makes use of <a href="https://views.grails.org/latest/">JSON Views</a> to customize the JSON output from our endpoints.</p>
-<p>No update or delete functions are provided at this time. Those features are left as an exercise to the reader.</p>
-<p><a href="https://github.com/ZacharyKlein/sett-todolist">https://github.com/ZacharyKlein/sett-todolist</a></p>
-<p><img src="2016-05-28-img02.png" alt="" /></p>
-<p>Completed TodoList app</p>
-<h2>Testing</h2>
-<p>One of the benefits of creating a user interface in React is testability. Because React encourages the use of stateless components, testing their functionality is often as simple as providing props and making assertions against their output. Let’s look at a simple test for our component, and then see how the Gradle node plugin can help us run our tests as part of our build.</p>
-<p>There are many options for testing Javascript code. [7,8] In this example we'll use the <a href="https://mochajs.org/">mocha test framework</a>, React’s own <a href="https://facebook.github.io/react/docs/test-utils.html">testing utilities</a>, and <code>expect.js</code> to provide assertions.</p>
-<p>Again, because React is focused on building our view layer, we’re mostly concerned with testing that our components output the correct content from their props. This is <em>not</em> an in-depth look at testing React components, but it will give you a place to start.</p>
-<p>First, let’s install some dependencies:</p>
-<pre><code> npm install mocha expect react-addons-test-utils --save-dev
-</code></pre>
-<p>And add this "test" script to our <code>package.json</code> file:</p>
-<pre><code> ”test": "mocha './src/test/js/*.spec.js' --compilers js:babel-core/register"
-</code></pre>
-<p>Here's a simple test for our component:</p>
-<pre><code class="language-javascript"> // /src/test/js/lot.spec.js
-
- import React from 'react';
- import TestUtils from 'react-addons-test-utils';
- import expect from 'expect';
- import Todo from '../../main/js/todo';
-
- describe('Todo', () => {
- it('should have expected content', () => {
-
- const todo = {name: 'Task 1', complete: false, id: 1, list: { id: 1 }};
-
- const renderer = TestUtils.createRenderer();
-
- renderer.render(
- <Todo todo={todo} ></Todo>);
-
- const output = renderer.getRenderOutput();
-
- //We expect the <Todo> to output an <li> element
- expect(output.type).toBe('li');
-
- const children = output.props.children;
- const [input, span] = children;
-
- //We expect the first element in our <li> to be an input
- expect(input.type).toBe('input');
-
- const todoName = span.props.children;
-
- //We expect the span to contain the name of the todo
- expect(todoName).toBe(todo.name);
- });
- });
-</code></pre>
-<p>There’s a lot to unpack here that is beyond the scope of this article, so I’ll refer you to the resources at the bottom of the page for more detail. But the big picture is fairly simple. We’ve created a “mock” todo object, and used it to populate our component, which is then “rendered” using <code>TestUtils.createRenderer()</code> (<code>TestUtils</code> also includes features for simulating clicks and other user interactions with your components). At that point, we’re simply traversi [...]
-<p>To run this test, use <code>npm</code> to run our new <code>test</code> script:</p>
-<pre><code> npm run test
-</code></pre>
-<pre><code class="language-javascript"> > todo-list@1.0.0 test /Users/zak/Dev/TodoList
- > mocha './src/test/js/*.spec.js' --compilers js:babel-core/register
-
- Todo
- ✓ should have expected content
-
- 1 passing (15ms)
-</code></pre>
-<p>Finally, we can add this test script to our Gradle build using the same techniques we explored earlier.</p>
-<pre><code class="language-groovy"> //build.gradle
-
- //Run React tests
- task mochaTest(dependsOn: ['npmInstall', 'npm_run_test'])
-
- check.dependsOn(mochaTest)
-</code></pre>
-<p>Now we can run our React tests via Gradle with <code>./gradlew mochaTest</code>, and they will also be run as part of the <code>check</code> task (which runs Grails unit and integration tests together).</p>
-<h2>Conclusion</h2>
-<p>React is a powerful and exciting library, and it’s a great choice for Grails applications. While there’s some bootstrapping necessary to get started, with a project structure like we’ve demonstrated you should be able to take advantage of the many resources available for learning React and associated libraries and tools, without having to “translate” into a Grails-specific flavor. In addition, front-end developers unfamiliar with Grails should find it much easier to work using their f [...]
-<blockquote>
-<p>Postscript</p>
-<p>As mentioned earlier in the article, I've created a <a href="https://github.com/ZacharyKlein/grails-react-starter">starter project</a> with React integrated in a Grails application, using the same structure described above. It also provides a working configuration for the <code>webpack-dev-server</code>, including a custom taglib to switch between the “hot load” bundle and the static bundle from the Grails asset pipeline. React-Bootstrap and loading of images and CSS are also demonstr [...]
-</blockquote>
-<h2>References</h2>
-<ul>
-<li>[1] Sample App: <a href="https://github.com/ZacharyKlein/sett-todolist">https://github.com/ZacharyKlein/sett-todolist</a></li>
-<li>[2] Grails-React Starter: <a href="https://github.com/ZacharyKlein/grails-react-starter">https://github.com/ZacharyKlein/grails-react-starter</a></li>
-<li>[3] Gradle-node-plugin: <a href="https://github.com/srs/gradle-node-plugin">https://github.com/srs/gradle-node-plugin</a></li>
-<li>[4] JSX and “Separation of concerns”: <a href="https://blog.andrewray.me/youre-missing-the-point-of-jsx/">https://blog.andrewray.me/youre-missing-the-point-of-jsx/</a></li>
-<li>[5] Why and how to bind methods in your React component classes?: <a href="https://reactkungfu.com/2015/07/why-and-how-to-bind-methods-in-your-react-component-classes/">https://reactkungfu.com/2015/07/why-and-how-to-bind-methods-in-your-react-component-classes/</a></li>
-<li>[6] Fetch API: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch">https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch</a></li>
-<li>[7] How we unit test React components using expect-jsx: <a href="https://blog.algolia.com/how-we-unit-test-react-components-using-expect-jsx/">https://blog.algolia.com/how-we-unit-test-react-components-using-expect-jsx</a></li>
-<li>[8] How React Components Make UI Testing Easy <a href="https://www.toptal.com/react/how-react-components-make-ui-testing-easy">https://www.toptal.com/react/how-react-components-make-ui-testing-easy</a></li>
-</ul>
-<h2>Resources</h2>
-<ul>
-<li>OCI Training in React Web Development: <a href="https://ocitraining.com/react-web-development/">https://ocitraining.com/react-web-development</a></li>
-<li>Egghead.io video courses on React and related technologies: <a href="https://egghead.io/q/react">https://egghead.io/q/react</a></li>
-<li>Navigating the React.JS Ecosystem: <a href="https://www.toptal.com/react/navigating-the-react-ecosystem">https://www.toptal.com/react/navigating-the-react-ecosystem</a></li>
-<li>An excellent set of sample React apps written and maintained by my OCI colleague, Mark Volkmann: <a href="https://github.com/mvolkmann/react-examples">https://github.com/mvolkmann/react-examples</a></li>
-<li>RubyC presentation by <a href="https://alexbcoles.com/">Alex Coles</a>, “Beyond the Asset Pipeline” (Rails-specific talk, but much of the discussion is relevant to the Grails asset pipeline as well): <a href="https://youtu.be/CNv9ewmQys8">https://youtu.be/CNv9ewmQys8</a></li>
-<li>How to Use Webpack with Rails (also Rails-specific, but many of the techniques described are relevant to Grails projects): <a href="https://clarkdave.net/2015/01/how-to-use-webpack-with-rails/">https://clarkdave.net/2015/01/how-to-use-webpack-with-rails/</a></li>
-</ul>
-<h2>Documentation</h2>
-<ul>
-<li>React Documentation: <a href="https://github.com/ZacharyKlein/grails-react-starter">https://facebook.github.io/react/docs/getting-started.html</a></li>
-<li>React Test-Utils: <a href="https://facebook.github.io/react/docs/test-utils.html">https://facebook.github.io/react/docs/test-utils.html</a></li>
-<li>JSX Documentation: <a href="https://github.com/ZacharyKlein/grails-react-starter">https://facebook.github.io/react/docs/jsx-in-depth.html</a></li>
-<li>Webpack Documentation: <a href="https://webpack.js.org/concepts/">https://webpack.js.org/concepts/</a></li>
-</ul>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-02-09.jpg)'>
- <a href='https://grails.org/blog/2018-02-09.html'>
- <h3>February 9, 2018</h3>
- <h2>Webinar: Developing React Apps with Grails® 3</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2017-11-21.jpg)'>
- <a href='https://grails.org/blog/2017-11-21.html'>
- <h3>November 21, 2017</h3>
- <h2>Grails® React Profiles</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2017-10-30.html'>
- <h3>October 30, 2017</h3>
- <h2>Quickcast #8: Grails® React Profile</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-05-28.html">https://grails.apache.org/blog/2016-05-28.html</a></p>
</body>
</html>
diff --git a/blog/2016-05-31.html b/blog/2016-05-31.html
index 34e96e0f58..cf998bd9d8 100644
--- a/blog/2016-05-31.html
+++ b/blog/2016-05-31.html
@@ -1,172 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Grails® 3.2 Milestone 1 Released</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Grails 3.2. M1 release announcement" />
- <meta name="date" content="May 31, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Grails 3.2. M1 release announcement'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Grails® 3.2 Milestone 1 Released'/>
- <meta property='og:description' content='Grails 3.2. M1 release announcement'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-05-31.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Grails® 3.2 Milestone 1 Released</h1>
-<p><span class="author">By Graeme Rocher</span></p>
-<p><span class="date">May 31, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/release.html"><span class="hashtag">#release</span></a></p>
-<p>Today, and just in time for <a href="https://gr8conf.eu/">GR8Conf EU</a> in Copenhagen, we are pleased to announce the <a href="https://github.com/grails/grails-core/releases/tag/v3.2.0.M1">first milestone of Grails<sup>®</sup> 3.2</a>, which includes the following new features.</p>
-<h2>RxGORM</h2>
-<p>Grails 3.2 milestone 1 ships with GORM 6.0 milestone 1, which includes a new implementation of GORM based on RxJava called RxGORM. With RxGORM you can build non-blocking, reactive applications using a familiar GORM API including features such as Where Queries, Dynamic Finders and Criteria Queries.</p>
-<p>With the initial release, support for MongoDB is included, but more implementations are planned for SQL, REST client, and other implementations. See the <a href="https://gorm.grails.org/latest/rx/manual/index.html">RxGORM Documentation</a> for more information.</p>
-<h2>Angular Scaffolding</h2>
-<p>Grails 3.2 features support for scaffolding of AngularJS 1.x applications (support for Angular 2 is also planned) when using the <code>angular</code> profile, allowing your team to quickly get up and running integrating Angular frontends with Grails 3 backends.</p>
-<h2>Improvements to JSON Views</h2>
-<p>JSON views, a feature introduced in Grails 3.1, have been drastically improved with support for template inheritance, global templates, extended HAL support and more.</p>
-<p>See the <a href="https://views.grails.org/1.1.0.M2/#_version_history">documentation for the 1.1 milestone 2 version</a> of the JSON views plugin for more information.</p>
-<h2>What's Still Coming?</h2>
-<p>Grails 3.2 is at the milestone phase and is not feature complete, still in the pipeline are the following new features:</p>
-<ul>
-<li>Native GORM Multi Tenancy Support</li>
-<li>RxGORM REST Client</li>
-<li>GORM for Neo4j 3.0 / Bolt Driver Support</li>
-<li>RxJava Controller Support</li>
-<li>Further AngularJS and REST Refinements</li>
-</ul>
-<p>For more information on the Milestone 1 release, check out the release notes.</p>
-<p>We look forward your feedback, and if you are coming to <a href="https://gr8conf.eu/">GR8Conf EU</a>, we look forward to talking to you more about the great new features coming in the Grails framework.</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2019-07-11.jpg)'>
- <a href='https://grails.org/blog/2019-07-11.html'>
- <h3>July 11, 2019</h3>
- <h2>Grails® 4 GA Released</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2019-02-19.jpg)'>
- <a href='https://grails.org/blog/2019-02-19.html'>
- <h3>February 19, 2019</h3>
- <h2>Grails® 4 Milestone 1 Released</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2017-07-26.jpg)'>
- <a href='https://grails.org/blog/2017-07-26.html'>
- <h3>July 26, 2017</h3>
- <h2>Grails® 3.3 GA Released</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-05-31.html">https://grails.apache.org/blog/2016-05-31.html</a></p>
</body>
</html>
diff --git a/blog/2016-06-02.html b/blog/2016-06-02.html
index bc41d96434..47bcf9a2c6 100644
--- a/blog/2016-06-02.html
+++ b/blog/2016-06-02.html
@@ -1,158 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Monitoring and Metrics with Grails® 3</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Jeff Scott Brown discusses monitoring and metrics with Grails 3 at GR8Conf EU 2016." />
- <meta name="date" content="June 2, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='player'/><meta name='twitter:player' content='https://www.youtube.com/embed/wVpEsbzMj90' />
-<meta name='twitter:player:width' content='560' />
-<meta name='twitter:player:height' content='315' />
-
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Jeff Scott Brown discusses monitoring and metrics with Grails 3 at GR8Conf EU 2016.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Monitoring and Metrics with Grails® 3'/>
- <meta property='og:description' content='Jeff Scott Brown discusses monitoring and metrics with Grails 3 at GR8Conf EU 2016.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-06-02.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Monitoring and Metrics with Grails® 3</h1>
-<p><span class="author">By Jeff Scott Brown</span></p>
-<p><span class="date">June 2, 2016</span></p>
-<p>tags: <a href="https://grails.org/blog/tag/monitoring.html"><span class="hashtag">#monitoring</span></a> <a href="https://grails.org/blog/tag/video.html"><span class="hashtag">#video</span></a></p>
-<p>Jeff Scott Brown, co-founder of the Grails<sup>®</sup> framework, discusses monitoring and metrics with Grails 3 at GR8Conf EU 2016.</p>
-<p>In this presentation, Jeff demonstrates capabilities that are currently in development with the intention of soliciting feedback from the Grails community. He also introduces features of Grails 3 and Groovy.</p>
-<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/wVpEsbzMj90" frameborder="0"></iframe>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-03-introducing-grails-6-2-3.html'>
- <h3>January 3, 2025</h3>
- <h2>Introducing Grails Framework 6.2.3 Release</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-02-grails-community-rockstar-fredley.html'>
- <h3>January 2, 2025</h3>
- <h2>James Fredley Named 2025 Grails® Rock Star</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-06-02.html">https://grails.apache.org/blog/2016-06-02.html</a></p>
</body>
</html>
diff --git a/blog/2016-06-07.html b/blog/2016-06-07.html
index e35717656a..e16381f16a 100644
--- a/blog/2016-06-07.html
+++ b/blog/2016-06-07.html
@@ -1,215 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>GR8Conf EU 2016 Wrap-up!</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="GR8Conf EU 2016 Wrap-up!" />
- <meta name="date" content="June 7, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='GR8Conf EU 2016 Wrap-up!'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='GR8Conf EU 2016 Wrap-up!'/>
- <meta property='og:description' content='GR8Conf EU 2016 Wrap-up!'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-06-07.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>GR8Conf EU 2016 Wrap-up!</h1>
-<p><span class="author">By Ryan Vanderwerf</span></p>
-<p><span class="date">June 7, 2016</span></p>
-<p><img src="2016-06-07-img01.jpg" alt="The OCI Team at GR8Conf EU 2016" /></p>
-<p>Well I've just started to clear my jet-lagged head getting back from <a href="https://gr8conf.eu/">GR8Conf EU</a> in Copenhagen, where <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) was a platinum sponsor this year. Lots of good stuff came out of the show, things announced, good workshops. This also was the first year there were 3 concurrent tracks for the EU edition. This worked out quite well and gave a good variety for everyone. There was also a university [...]
-<p><img src="2016-06-07-img02.jpg" alt="CPH View" /></p>
-<h2>Day 1: Workshops</h2>
-<p>I started the day doing my Groovy Lego Mindstorms EV3 talk where we worked with putting Groovy apps on the robots, then used the Grails<sup>®</sup> framework to control the robots like mars rovers.</p>
-<p><img src="2016-06-07-img03.jpg" alt="Lego" /></p>
-<p>Jeff Brown then did 2(!) back to back workshops on 'Getting Started with Grails 3' and 'Rest with Grails 3'. Andres Almiray did a Gradle workshop, Jacob Mikkelsen (Of Grails Diary fame) did a Groovy and Spock for beginners. Wrapping up was our own Alvaro Sanchez-Mariscal with a workshop on <a href="https://alvarosanchez.github.io/grails-angularjs-springsecurity-workshop/" title="Building Apps with Grails">building apps with the Grails framework, AngularJS, and Spring Security</a>. I t [...]
-<h3>Hackergarten on Tour</h3>
-<p>Andres Almiray led the Hackergarten this year again. His energy is very good and high which helps get people motivated for some open source contributions. Lots was done, I think several Spock issues merged, progress on Elastic Search 2 plugin for Grails 3, fixes for lazybones templates on Android Wear. One thing that will be good for the Grails framework is that there was lots of progress on a converter for the old gdoc format to ascii doctor <a href="https://t.co/NA41R1DUjM">here</a> [...]
-<h2>Day 2: Talks</h2>
-<p>Kenneth Kousen kicked off the conference with a great keynote that talked about all the value Groovy has and talked about the decisions by Gradle to make Kotlin first class and Groovy second going forward. Lots of good points about what everyone can do to make Groovy better and what makes the community great - and a big one is that maintainers are needed for the Grails framework and Groovy support for Eclipse. Will someone step up? It is hard to say because almost everyone at the show [...]
-<p>Here we start the 3 parallel tracks, with one being 'A Groovy journey in open source land' by Guillaume Laforge where we get a state of the union on Groovy. Following the Groovy track Jochen Theodorou talking about the new joint compiler which is very early. As an aside Jochen has started at Canoo (yay!), and unfortunately will have less time for Groovy now :( On a good note Cédric Champeau prepped a new release of Groovy 2.4.7 which is awaiting Apache approval for release.</p>
-<p>After lunch we fire up again with our very own Jeff Scott Brown talking about monitoring and metrics in Grails 3 with a dropwizard plugin, Noam on clean Groovy, and a panel on the future of Groovy. I went to the panel which was led by Cedric, Jochen, and Jennifer. It was a frank upbeat discussion starting out with ribbing Gradle on Kotlin of course, then talking about what can be done to help drive Groovy adoption forward. Again the Eclipse support bubbled to the top again. Average Jo [...]
-<p>I've heard following up that Marcin's talk on 'nooks and crannies of Spock' was quite good - lots to learn there. I didn't get a chance to attend the others but I peeked in the fame talk and looked interesting (does it archive?).</p>
-<p>After that I sat in on the 'Ask the Grails Experts' panel with myself, Jeff, Alvaro, and Graeme. Lots of questions came up about Grails 4(????) including will the upgrade be hard like 2.5 to 3.0. We're try our best but I don't think anyone knows what Grails 4 will look like yet :) Always lots of good questions answered about direction and features to keep everyone in the know, and a question on upgrading grails 2 -> 3 apps.</p>
-<p>Next slot was some Android and Gradle (Ken), Groovy gateway drug(Jacob), and Migration to Grails 3 by Michael Ploed which I heard was quite good and helpful.</p>
-<p><img src="2016-06-07-img04.jpg" alt="Gr8 Beer!" /></p>
-<p>Wrapping up the talks was Mario David on Dockerizing your Grails app, Groovy Parallel, and Scraping the web with Geb.</p>
-<p>Finishing the day, finally we get some of that Gr8 beer. They had 4 varieties this year, with the 4th one being a new Gradle IPA. Ironically a bitter beer for well um... (hrm did they know something that many months ago we didn't?) the world is weird like that.</p>
-<p>Noam Tenne and Baruch Sadogursky did an really fantastic job with the Groovy Puzzlers. Lots of shirts were handed out for some good puzzlers. I think I knew more of them than I ever have before, so either I am getting better at this stuff or they are getting easier :)</p>
-<h2>Day 3: Talks</h2>
-<p>We roll into day 3 running with talks about Grails 3 Plugins by our own Alvaro Sanchez-Mariscal, Jennifer Strater's CodeNarc revisited, and Sacha Klein's UI intro. Grame Rocher goes deeper into the new GORM 5 features and inner workings. Iván López from Greach talks about full stack development, and Danny Hyun gives an excellent Ratpack talk (and as of today Dan Wood's book is in print!).</p>
-<p>Graeme Rocher gives us a mid morning keynote before he has to jump on a plane, he showed us some new features of 3.2, RX-Gorm, and more.</p>
-<p>At this point I have to give my Alexa talk <a href="https://speakerdeck.com/rvanderwerf/alexa-tell-me-im-groovy-gr8conf-dot-eu-2016">slides here</a> which went pretty well. I also (re)membered Alexa doesn't understand 'Grails' well since it's not a real word which the crowd got a good chuckle at some random tweets it started reading :) I missed but heard Cedric's and Puneet's talks were very good.</p>
-<p>Next I attended Sergio del Amo's talk on building a conference app (for Greach) with Groovy, Android, and of all things Wordpress ;) very clever combination of things that seem to work well together. I missed Jennifer's talk on TDD for API Docs and Sacha Klein's talk on Groovy and Jenkins (which is something people either don't realize or forget about how much Jenkins uses Groovy!).</p>
-<p>Wrapping up the conference is Jeff Scott Brown's 'Testing in Grails 3', Kenneth Kousen's "Groovy Tips and Tricks", and Noam Tenne's talk about Dockerizing your Ratpack app.</p>
-<p>Some of the speakers got together for dinner after that at a Mexican place (I'm from Texas and was a bit puzzled this existed in Denmark heh) which is quite good! The next day some of the speakers still left in town did a Segway tour around the city. It looks geeky as heck, but it was pretty fun.</p>
-<p><img src="2016-06-07-img05.jpg" alt="Nerd Bike" /></p>
-<p>Special thanks to all the sponsors and Gr8Crew (especially Søren, Jacob, Niels, Brian and crew) that make the conference possible! It is a lot of work they do for many many months before the conference each year. This is the 3rd one I have spoken at and attended and the best yet. I'm sure 2017 will be even better. If you haven't been I recommend it. If it's far, take a tech-cation (As Burt Beckwith likes to call it) and see the beautiful city and learn something too. Maybe you can fin [...]
-<p>Also here is a Groovy podcast recorded at Gr8Conf.eu: <a href="https://www.youtube.com/watch?v=Sj9P6_jT9R8">Groovy Podcast Episode 28</a></p>
-<hr />
-<h2>Slide Decks From the Conference</h2>
-<p>(cobbled together and ripped from tweets, Grails Diary, and Groovy Calamari)</p>
-<ul>
-<li><a href="https://speakerdeck.com/rvanderwerf/alexa-tell-me-im-groovy-gr8conf-dot-eu-2016">Alexa, Tell Me I'm Groovy!</a> (Ryan Vanderwerf)</li>
-<li><a href="https://speakerdeck.com/szpak/interesting-nooks-and-crannies-of-spock-you-may-have-never-seen-before">Interesting nooks and crannies of Spock you (may) have never seen before</a> (Marcin Zaj?czkowski)</li>
-<li><a href="https://www.slideshare.net/alvarosanchezmariscal/creating-applications-with-grails-angular-js-and-spring-security-62646073">Creating applications with Grails, Angular JS and Spring Security</a> (Alvaro Sanchez-Mariscal)</li>
-<li><a href="https://speakerdeck.com/glaforge/a-groovy-journey-in-open-source-land">A Groovy journey in Open Source land</a> (Guillaume Laforge)</li>
-<li><a href="https://melix.github.io/gr8conf2016-intro-software-model/#/">Introduction to the Java software model</a> (Cédric Champeau)</li>
-<li><a href="https://melix.github.io/gr8conf2016-variant-aware-dep-mgmt/#/">Variant aware dependency management with Gradle</a> (Cédric Champeau)</li>
-<li><a href="https://speakerdeck.com/sdelamo/scraping-with-geb">Scraping with Geb</a> (Sergio del Amo)</li>
-<li><a href="https://t.co/2GsyZuq2h8">How to create a conference android app with Groovy and Android?</a> (Sergio del Amo)</li>
-<li><a href="https://speakerdeck.com/jlstrater/codenarc-revisited-gr8conf-eu-2016">Codenarc Revisited</a> (Jenn Strater)</li>
-<li><a href="https://danhyun.github.io/2016-gr8confeu-rapid-ratpack-groovy/#implementing_individual_todo_chain">Rapid Ratpack Groovy Web App Development</a> (Danny Hyun)</li>
-<li><a href="https://www.slideshare.net/alvarosanchezmariscal/mastering-grails-3-plugins-gr8conf-eu-2016">Mastering Grails 3 Plugins</a> (Alvaro Sanchez-Mariscal)</li>
-<li><a href="https://www.slideshare.net/ilopmar/gr8conf-2016-mum-i-want-to-be-a-groovy-fullstack-developer">Mum, I want to be a Groovy full-stack developer</a> (Iván López)</li>
-<li><a href="https://de.slideshare.net/sascha_klein/introduction-to-graphics-and-uidesign">Introduction to Graphics- and UI-Design</a> (Alexander (Sascha) Klein)</li>
-<li><a href="https://melix.github.io/gr8conf2016-deepdive-groovy-compiler/#/">Deep dive into the Groovy compiler</a> (Cédric Champeau)</li>
-<li><a href="https://speakerdeck.com/mariodavid/dockerize-your-grails-app-for-more-deployment-fun-gr8conf-eu-2016">Dockerize your Grails App for more deployment fun</a> (Mario David)</li>
-<li><a href="https://speakerdeck.com/behl/giving-back-to-the-grails-community-migrating-plugins-from-grails-2-to-grails-3">Giving back to the Grails Community - Migrating plugins from Grails 2 to Grails 3</a> (Puneet Behl)</li>
-<li><a href="https://speakerdeck.com/mariodavid/is-grails-the-right-approach-for-business-apps-gr8conf-eu-2016">Is Grails the right approach for business apps?</a> (Mario David)</li>
-<li><a href="https://www.slideshare.net/gr8conf/groovy-powered-clean-code">Groovy Powered Clean Code</a> (Noam Tenne)</li>
-<li><a href="https://de.slideshare.net/sascha_klein/using-groovy-with-jenkins">Using Groovy with Jenkins</a> (Alexander (Sascha) Klein)</li>
-<li><a href="https://www.slideshare.net/gr8conf/ratpack-on-the-docks">Ratpack On the Docks</a> (Noam Tenne)</li>
-<li><a href="https://speakerdeck.com/jlstrater/a-test-driven-approach-to-documenting-restful-apis-with-spring-rest-docs-gr8conf-eu-2016">Test Driven Approach to Documenting REST APIs w/ Spring REST Docs</a> (Jenn Strater)</li>
-<li><a href="https://www.innoq.com/de/talks/2016/06/hands-on-migration-grails-2-to-3/">Hands On Migration from Grails 2 to 3</a> (Michael Plöd)</li>
-<li><a href="https://www.innoq.com/de/talks/2016/06/reactive-applications-with-grails3/">Building reactive applications with the Grails 3 event system</a> (<a href="https://github.com/mploed/grails-event-example">code</a>) (Michael Plöd)</li>
-<li><a href="https://www.slideshare.net/ilopmar/gr8conf-2016-metaprogramming-with-groovy">Metaprogramming with Groovy</a> (Iván López)</li>
-<li><a href="https://www.slideshare.net/graemerocher/gr8conf-2016-whats-new-in-grails-3">Grails Keynote / What's New In Grails 3</a> (Graeme Rocher)</li>
-<li><a href="https://www.slideshare.net/graemerocher/gr8conf-2016-gorm-inside-and-out">GORM Inside and Out</a> (Graeme Rocher)</li>
-<li><a href="https://www.slideshare.net/aalmiray/gradle-glam-plugis-strike-back">Gradle Glam - Plugins Strike Back</a> (Andres Almiray)</li>
-</ul>
-<p>I look forward to the next edition!</p>
-<p>— Ryan Vanderwerf and the rest of the OCI/Grails Team</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-03-introducing-grails-6-2-3.html'>
- <h3>January 3, 2025</h3>
- <h2>Introducing Grails Framework 6.2.3 Release</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-02-grails-community-rockstar-fredley.html'>
- <h3>January 2, 2025</h3>
- <h2>James Fredley Named 2025 Grails® Rock Star</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-06-07.html">https://grails.apache.org/blog/2016-06-07.html</a></p>
</body>
</html>
diff --git a/blog/2016-06-26.html b/blog/2016-06-26.html
index b0dd6fe1fc..dd273c02a2 100644
--- a/blog/2016-06-26.html
+++ b/blog/2016-06-26.html
@@ -1,528 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Building Alexa Skills with the Grails® framework</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Learn to use Grails to write your own Alexa apps." />
- <meta name="date" content="June 26, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Learn to use Grails to write your own Alexa apps.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Building Alexa Skills with the Grails® framework'/>
- <meta property='og:description' content='Learn to use Grails to write your own Alexa apps.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-06-26.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Building Alexa Skills with the Grails® framework</h1>
-<p><span class="author">By Ryan Vanderwerf</span></p>
-<p><span class="date">June 26, 2016</span></p>
-<p><img src="2016-06-26-img01.jpg" alt="building spoken-language apps and experiences for Amazon Echo" /></p>
-<p>Recently I gave a talk at GR8Conf.eu about building applications for the Amazon Alexa platform. I talked about using Groovy with Lambdas to demonstrate Skills (Alexa Apps), as well as using the Grails<sup>®</sup> framework. I'll give this talk again at GR8Conf.us at the end of July and have even more good stuff to show. On top of that, after working on this for months, I have the material to deliver an Alexa workshop at GR8Conf.us (Thanks to Colin Harrington for helping with the idea) [...]
-<p>I wanted to write a post as a step-by-step on using a plugin I've recently developed to help you crank out Alexa apps (skills or speechlets). Amazon has a promotion right now: If you submit a new skill to their library, you can win a free t-shirt, so maybe you can make something cool with this and get one! You do not even need an Amazon device; you can point your browser to <a href="https://echosim.io/">https://echosim.io</a> to use their emulator.</p>
-<p><img src="2016-06-26-img02.png" alt="Echo-ism" /></p>
-<p>Let me first get started to explain how these things work and a little about the devices.</p>
-<p>Starting a couple years ago, Amazon released a home device/speaker thing called the Echo. It's a household helper device with very nice multi-directional microphones and a nice speaker for playing music.</p>
-<p>At first, I didn't get one or understand it; it sounded like a useless toy to me. However peers gobbled them up and started playing around with them. They weren't building apps for it but raved about how cool it was and how it helped them automate their homes and do useful things. Then they started saying they loved it so much they were buying more units and putting them all over their houses. Now my attention was had – of course the first thing that pops into my head was 'how can I g [...]
-<p><img src="2016-06-26-img03.jpg" alt="Things Alexa Can Do" /></p>
-<p>The first examples they give are all about AWS Lambda functions in Node; however they aren't fantastic on Java because they have a hard limit of 50mb jars you can upload. Surely you can't fit the whole Grails framework and dependencies in there to do much.</p>
-<p>Still, we gave it a shot. I followed Benoit Hédiard's <a href="https://skillsmatter.com/skillscasts/7291-serverless-microservices-using-aws-lambda-and-groovy">presentation</a> on Groovy with Lambdas from GGX 2015. I sat down with a buddy of mine, Lee Fox (he will be at GR8Conf.us), and we hammered out a bunch of ideas we could build with it – in Groovy of course!</p>
-<p>The first app we got working was a simple Twitter app that combined Groovy, Spring Social, and Skills to make a skill that would connect to Twitter and search for tweets, as well as give updates to your timeline. You can find the code <a href="https://github.com/rvanderwerf/alexa-twitter-groovy">here</a>.</p>
-<p>Good! Now we're getting somewhere. I did a little digging and found they have some servlet support to make a standalone web service – now we can get Grails involved and make this less hideous.</p>
-<p>Next we took it a level up. We didn't want the user to have to hard-code their Twitter API keys to run the app, and you can't publish a skill that pulls down someone else's Twitter info. So we built a Grails app that used Spring Security, Oath plugin, and Spring Security UI to allow a UI that lets you register and enter your own Twitter keys for your account. Source for that is <a href="https://github.com/rvanderwerf/twitterAuth">here</a>.</p>
-<p>After that, it was time to make a plugin to help you make these skills, which I published while I was out at GR8Conf.eu <a href="https://github.com/rvanderwerf/grails-alexa-skills">here</a>. It works similar to the Quartz plugin, in that you have a CLI command to create a working template of a Skill to get you started.</p>
-<p>I will show you here how to build a skill using the Grails plugin to get you started making your own Skills in a short amount of time.</p>
-<h2>How Alexa Service Works</h2>
-<p>The devices themselves, (which are currently the Echo, Tap, Dot, and FireTV) don't do a whole lot. They even publish the source to the devices for you to look at if you choose <a href="https://www.amazon.com/gp/help/customer/display.html?nodeId=201626480">here</a>.</p>
-<p>The magic resides on the Amazon side that handles all the voice recognition and handling of requests. Basically what happens is the user initiates an action (skill) on the device, and it goes to the alexa service to figure out what you want to do. When your app is invoked, it calls back to your app via a JSON HTTPS call and initiates a series of Intents to make your app do things. Your app simply waits for the call and takes appropriate action (via JSON) to do what you want. It's up t [...]
-<p><img src="2016-06-26-img04.jpg" alt="Alexa Appkit Architecture" /></p>
-<p>The picture above gives you an idea of how it works (from Amazon's site). Let's go over Intents and Sample utterances to have a better idea of what's going on.</p>
-<h2>Intents</h2>
-<p>Intents are sort of like simplified Intents on android if you have ever done Android coding. They signal an intention for a command to run to do something.</p>
-<p>Let's look at an example one to get an idea:</p>
-<pre><code class="language-json">{
- "intents": [
- {
- "intent": "ResponseIntent",
- "slots": [
- {
- "name": "Answer",
- "type": "AMAZON.LITERAL"
- }
- ]
- },
- {
- "intent": "QuestionCountIntent",
- "slots": [
- {
- "name": "Count",
- "type": "AMAZON.NUMBER"
- }
- ]
- },
- {
- "intent": "AMAZON.HelpIntent"
- }
- ]
-}
-</code></pre>
-<p>Here this application can trigger three intents:</p>
-<ol>
-<li>ResponseIntent</li>
-<li>QuestionCountIntent</li>
-<li>HelpIntent</li>
-</ol>
-<p>You use JSON to tell it what these are.</p>
-<p>You can define 'slots,' which are the expected responses. They comprise a name and Type. There are pre-defined data types you can use to help Amazon parse what is said. Number for example knows the user is going to say a number. Literal is a simple String. Some intents, like the help intent, don't need anything, as they are 'built in' (no inputs).</p>
-<p>A little bit about slots:</p>
-<p>They are entirely optional. You can do things like define a list of allowed responses (custom slots) that are valid things for the user to say. In this case the ResponseIntent is free form, and we sort out what we want to do by parsing the string we get from Amazon (translated via TTS).</p>
-<h2>Sample Utterances</h2>
-<p>Let's look at another example:</p>
-<pre><code> ResponseIntent {test|Answer}
- ResponseIntent {last player|Answer}
- ResponseIntent {test test|Answer}
- ResponseIntent {test test test|Answer}
- ResponseIntent {test test test test|Answer}
- QuestionCountIntent {Count} questions
-</code></pre>
-<p>Here we see the intent each utterances (what the person says) and map it to an intent.</p>
-<ul>
-<li>Amazon will generate common words like conjunctions and ignored things on their end, so you don't have to mess with handling things like 'and', 'the', 'or' etc.</li>
-<li>Variables are surrounded by {}.</li>
-<li>You can use the | operator to specify alternate options.</li>
-</ul>
-<p>If you want to say something to your skill, it must match the pattern here. For this case, we want to parse multi-world answers to a question. Basically, here we support one, two, three, or four word responses – anything else will be cut off/ignored.</p>
-<p>The last item allows the user to answer how many questions they want to be asked.</p>
-<h2>Requirements</h2>
-<ul>
-<li>A publicly available container (Self running Grails jar, Tomcat, Elastic Beanstalk, etc) to launch your app with HTTPS on port 443 (no way around this). Can be self-signed for DEV mode only.</li>
-<li>If you want to use audio snippets via SSML, they must be hosted as above, but with a recognized CA (no self-signed). S3 Static HTTPS buckets are easiest.</li>
-<li>SSL Certificate common name MUST match hostname (even for self-signed DEV certs)</li>
-</ul>
-<h2>Let's Make a Grails App Using the Plugin and I Will Explain More as We Go</h2>
-<p>The plugin is for Grails 3.x only. Let's create a new app first:</p>
-<pre><code> grails create-app skillsTest
-</code></pre>
-<p>Now let's open build.gradle and add the plugin into the dependencies {} closure:</p>
-<pre><code> compile "org.grails.plugins:alexa-skills:0.1.1"
-</code></pre>
-<p>Now let's create a skill from the command line:</p>
-<pre><code> grails create-speechlet SkillsTest
- | Rendered template Speechlet.groovy to destination grails-app/speechlets/skillstest/SkillsTestSpeechlet.groovy
-</code></pre>
-<p>Now let's see what it's created in grails-app/speechlets:</p>
-<pre><code class="language-groovy">@Slf4j
-class SkillsTestSpeechlet implements GrailsConfigurationAware, Speechlet {
-
- def grailsApplication
-
- Config grailsConfig
- def speechletService
-
-
- def index() {
- speechletService.doSpeechlet(request,response, this)
- }
-
- /**
- * This is called when the session is started
- * Add an initialization setup for the session here
- * @param request SessionStartedRequest
- * @param session Session
- * @throws SpeechletException
- */
- public void onSessionStarted(final SessionStartedRequest request, final Session session)
- throws SpeechletException {
- log.info("onSessionStarted requestId={}, sessionId={}", request.getRequestId(),
- session.getSessionId())
-
- }
-
- /**
- * This is called when the skill/speechlet is launched on Alexa
- * @param request LaunchRequest
- * @param session Session
- * @return
- * @throws SpeechletException
- */
- public SpeechletResponse onLaunch(final LaunchRequest request, final Session session)
- throws SpeechletException {
- log.info("onLaunch requestId={}, sessionId={}", request.getRequestId(),
- session.getSessionId())
-
- return getWelcomeResponse()
- }
-
- /**
- * This is the method fired when an intent is called
- *
- * @param request IntentRequest intent called from Alexa
- * @param session Session
- * @return SpeechletResponse tell or ask type
- * @throws SpeechletException
- */
- public SpeechletResponse onIntent(final IntentRequest request, final Session session)
- throws SpeechletException {
- log.info("onIntent requestId={}, sessionId={}", request.getRequestId(),
- session.getSessionId())
-
- log.debug("invoking intent:${intentName}")
- PlainTextOutputSpeech speech = new PlainTextOutputSpeech()
- // Create the Simple card content.
- SimpleCard card = new SimpleCard(title:"Twitter Search Results")
- def speechText = "I will say something"
- def cardText = "I will print something"
- // Create the plain text output.
- speech.setText(speechText)
- card.setContent(cardText)
- SpeechletResponse.newTellResponse(speech, card)
-
- }
- /**
- * Grails config is injected here for configuration of your speechlet
- * @param co Config
- */
- void setConfiguration(Config co) {
- this.grailsConfig = co
- }
-
- /**
- * this is where you do session cleanup
- * @param request SessionEndedRequest
- * @param session
- * @throws SpeechletException
- */
- public void onSessionEnded(final SessionEndedRequest request, final Session session)
- throws SpeechletException {
- log.info("onSessionEnded requestId={}, sessionId={}", request.getRequestId(),
- session.getSessionId())
- // any cleanup logic goes here
- }
-
- SpeechletResponse getWelcomeResponse() {
- String speechText = "Say something when the skill starts"
-
- // Create the Simple card content.
- SimpleCard card = new SimpleCard(title: "YourWelcomeCardTitle", content: speechText)
-
- // Create the plain text output.
- PlainTextOutputSpeech speech = new PlainTextOutputSpeech(text:speechText)
-
- // Create reprompt
- Reprompt reprompt = new Reprompt(outputSpeech: speech)
-
- SpeechletResponse.newAskResponse(speech, reprompt, card)
- }
-
- /**
- * default responder when a help intent is launched on how to use your speechlet
- * @return
- */
- SpeechletResponse getHelpResponse() {
- String speechText = "Say something when the skill need help"
- // Create the Simple card content.
- SimpleCard card = new SimpleCard(title:"YourHelpCardTitle",
- content:speechText)
- // Create the plain text output.
- PlainTextOutputSpeech speech = new PlainTextOutputSpeech(text:speechText)
- // Create reprompt
- Reprompt reprompt = new Reprompt(outputSpeech: speech)
- SpeechletResponse.newAskResponse(speech, reprompt, card)
- }
-
- /**
- * if you are using account linking, this is used to send a card with a link to your app to get started
- * @param session
- * @return
- */
- SpeechletResponse createLinkCard(Session session) {
-
- String speechText = "Please use the alexa app to link account."
- // Create the Simple card content.
- LinkAccountCard card = new LinkAccountCard()
- // Create the plain text output.
- PlainTextOutputSpeech speech = new PlainTextOutputSpeech(text:speechText)
- log.debug("Session ID=${session.sessionId}")
- // Create reprompt
- Reprompt reprompt = new Reprompt(outputSpeech: speech)
- SpeechletResponse.newTellResponse(speech, card)
- }
-
-}
-</code></pre>
-<p>Also the plugin will generate a Controller class embedded in your Speechlet file. If you are using Spring Security, you will want to make sure that uri is accessible to the outside to the Alexa service can contact it (there are some requirements I'll fill you in on later):</p>
-<pre><code class="language-groovy">/**
- * this controller handles incoming requests - be sure to white list it with SpringSecurity
- * or whatever you are using
- */
-@Controller
-class SkillsTestController {
-
- def speechletService
- def skillsTestSpeechlet
-
-
- def index() {
- speechletService.doSpeechlet(request,response, skillsTestSpeechlet)
- }
-
-}
-
-</code></pre>
-<p>The speechlet artefact will be registered as a Spring bean so it's automatically injected. There is also a service the plugin provides to handle the boring stuff like verifying the request, checking the app ID (more on that later) and the plumbing that calls your skill.</p>
-<h2>Built-in Events</h2>
-<p>Looking at the code example above, you can see it made several methods for you. These are part of the skill (speechlet) lifecycle. The first one is:</p>
-<h3><code>onSessionStarted</code></h3>
-<p>This allows you to store variables for the duration of the session (the interactions as a whole of the app for that time). You can do some setup here and store variables you can use later. This is technically optional for you to implement.</p>
-<h3><code>onLaunch</code></h3>
-<p>This is called when you invoke the skill. When you say 'Alexa open skillTest' etc. this is you chance to say an opening message about your app, what it does, or what they will need to do.</p>
-<h3><code>onIntent</code></h3>
-<p>This is the meat and is required to be implemented. When your sample utterances maps to an Intent when the user says something this is invoked.</p>
-<p>Here you should generate a card that will appear in the Alexa app on your phone (you can also get to this on your local network via browser by going to 'echo.amazon.com'. Cards are similar to Android cards (more popular in Android Wear) that simply show a message to the user so they can see what is going on.</p>
-<p>You can make several kinds of cards which are Simple, Standard, and LinkAccount. Here we have a switch statement to figure out what Intent to process and call the code for the appropriate intent.</p>
-<h3><code>onSessionEnded</code></h3>
-<p>This is the last one, optional, where you can clean up session resources you might have created like database records for the run.</p>
-<p>I've added a few other helper methods to see how to render a help response, link an account, and get some setup details from the Grails config. As a first pass, just try to get the default template working, then start to change things like changing the text, add an Intent, etc.</p>
-<h2>Set Up Your App on Amazon Developer Portal</h2>
-<p>This is separate from AWS. I am not aware of any APIs that will create all of this for you so you have to sign up for an account and do this by hand for each skill you want to run.</p>
-<p><img src="2016-06-26-img05.png" alt="Amazon Developer Portal" /></p>
-<ul>
-<li>
-<p>Pull down the 'twitterAuth' app <a href="https://github.com/rvanderwerf/twitterAuth">here</a> to get some Intents/Sample utterances to try. They are located in src/main/resources.</p>
-</li>
-<li>
-<p>Sign up for the Amazon developer program <a href="https://developer.amazon.com/">here</a> if you haven't already</p>
-</li>
-<li>
-<p>Click on Apps and Services -> Alexa</p>
-</li>
-<li>
-<p>Click on Alexa Skill Kit / Get Started -> Add New Skill</p>
-</li>
-</ul>
-<p><img src="2016-06-26-img06.png" alt="Create a New Alexa Skill" /></p>
-<ul>
-<li>Pick any name and any invocation name you want to start the app on your Echo / Alexa Device</li>
-</ul>
-<p><img src="2016-06-26-img07.png" alt="Interaction Model" /></p>
-<ul>
-<li>
-<p>Copy the contents of src/main/resources/IntentSchema.json into Intent Schema.</p>
-</li>
-<li>
-<p>Don't fill in anything for slots</p>
-</li>
-<li>
-<p>Under Sample Utterances, copy the contents of the file src/main/resources/SampleUtterances.txt</p>
-</li>
-</ul>
-<p><img src="2016-06-26-img08.png" alt="Configuration" /></p>
-<ul>
-<li>
-<p>Under configuration copy the url for /twitterAuth/twitter/index for the endpoint for your server (choose amazon https not ARN). Click next.</p>
-</li>
-<li>
-<p>Leave 'enable account linking' turned off.</p>
-</li>
-<li>
-<p>For domain list, enter a domain that matches your SSL cert the oauth tokens will be valid for. You may use a self-signed cert for development mode, but if you want to publish your skill, your server will need to be running a real recognized certificate (a cheap option is RapidSSL).</p>
-</li>
-<li>
-<p>Enter the url for the privacy policy on your server. It can be any valid web page, a link will show during account linking in the alexa app</p>
-</li>
-<li>
-<p>Hit Save</p>
-</li>
-<li>
-<p>Click on SSL Certificate. If you have a self-signed cert (will only work for DEV mode) paste it here under 'I will upload a self-signed certificate in X.509 format.'</p>
-</li>
-<li>
-<p>Hit Save and go to Test page and hit Save</p>
-</li>
-</ul>
-<p><img src="2016-06-26-img09.png" alt="Test" /></p>
-<ul>
-<li>Go to Privacy and Compliance, and fill out the info there (It's required)</li>
-</ul>
-<p>Now note the application ID it gives you. You will need to add this to the application.groovy/yml file so the application will know the app ID and accept it.</p>
-<p>Copy the application ID on the first tab 'SKILL INFORMATION', and paste that into application.groovy</p>
-<pre><code>alexaSkills.supportedApplicationIds="amzn1.echo-api.request.8bd8f02f-5b71-4404-a121-1b0385e56123,amzn1.echo-sdk-ams.app.84d004e5-e084-4087-a8c3-a80b12fd2009,amzn1.echo-sdk-ams.app.dc1dea0e-ab91-446d-a1c7-460df5e83489"
- alexaSkills.disableVerificationCheck = true // helpful for debugging or replay a command via curl
- alexaSkills.serializeRequests = true // this logs the requests to disk to help you debug
- alexaSkills.serializeRequestsOutputPath = "/tmp/"
-</code></pre>
-<p>Build and deploy your war file to your server (btw, it must be port 443 HTTPS, no exceptions).</p>
-<h2>Test Your App</h2>
-<p>Now try it on your Echo/Alexa device. Say either 'start' or 'open' and the invocation name you gave the app and follow the prompts! You can also use the test function on the portal itself.</p>
-<h2>Debugging</h2>
-<p>Debugging can be very frustrating. Make sure to turn your log level to debug. In the Grails config, there is an option called 'serializeRequests' and a output path for them. This allows you to capture the request that came from Amazon. If you are trying to test a fix for a bug, you can replay this via CURL. The files will look like this:</p>
-<pre><code> -rw-r--r-- 1 tomcat tomcat 598 Jun 6 22:45 speechlet-1465249551692.out
- -rw-r--r-- 1 tomcat tomcat 636 Jun 6 22:45 speechlet-1465249557538.out
- -rw-r--r-- 1 tomcat tomcat 598 Jun 6 22:46 speechlet-1465249601675.out
- -rw-r--r-- 1 tomcat tomcat 636 Jun 6 22:46 speechlet-1465249607216.out
-</code></pre>
-<p>The built-in security provided by the plugin and underlying library will now allow you to reuse a request because the hashed timestamps are too old (to prevent this type of attack called a 'replay attack'). You can disable this check for dev purposes with the 'disableVerificationCheck' Grails config value. Now you can replay a file via CURL back to your server to avoid the whole voice interaction to test that one case (and test it locally!):</p>
-<pre><code> curl -vX POST http://localhost:8080/test/index -d @speechlet-14641464378122470.out --header "Content-Type: application/json"
-</code></pre>
-<p>If you save enough requests of a normal interaction, you could write some functional tests that replay this as part of a test suite or just be able to dev against them locally a bit.</p>
-<h2>Advanced Stuff: Full UI with Spring Security, OAuth</h2>
-<p>If you want a UI for the user and use account linking, an easy path is to add Spring Security, Spring Security UI, Spring Security OAuth Grails plugins. You can see an example of how to do this <a href="https://github.com/rvanderwerf/twitterAuth">here</a>.</p>
-<h2>Advanced Stuff: Say Sample Audio Clips in Your Skill</h2>
-<p>There is a supported markup called SSML which allows up to 90 seconds of low quality mp3 sound clips to play. Their settings/requirements are quick picky to work:</p>
-<ul>
-<li>Must be hosted on a recognized CA HTTPS port 443 server (I use S3 static website for this)</li>
-<li>Must be 16khz, 48 kb/s MP3 files</li>
-<li>Use the open source tool 'ffmpeg' to encode them - these settings work: 'ffmpeg -y -i -ar 16000 -ab 48k -codec:a libmp3lame -ac 1 file.mp3'</li>
-<li>See the <a href="https://github.com/rvanderwerf/heroQuiz">heroQuiz</a> app for an example of playback sounds being used.</li>
-</ul>
-<p>Example SSML</p>
-<pre><code> <speak>
- <audio src="\"https://s3.amazonaws.com/vanderfox-sounds/groovybaby1.mp3\"/"> ${speechText}
- </audio>
- </speak>
-</code></pre>
-<h2>Useful links</h2>
-<ul>
-<li>Emulator: <a href="https://echosim.io/">https://echosim.io</a></li>
-<li>Account Linking: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/linking-an-alexa-user-with-a-user-in-your-system">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/linking-an-alexa-user-with-a-user-in-your-system</a></li>
-<li>Getting Started Guide: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/getting-started-guide">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/getting-started-guide</a></li>
-<li>Custom Skill Overview: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/overviews/understanding-custom-skills">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/overviews/understanding-custom-skills</a></li>
-<li>Defining the Voice Interface: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/defining-the-voice-interface">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/defining-the-voice-interface</a></li>
-<li>Voice Design Handbook: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-voice-design-handbook">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-voice-design-handbook</a></li>
-<li>Custom Skill JSON reference: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference</a></li>
-<li>SSML Reference: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference</a></li>
-</ul>
-<h2>Conclusion</h2>
-<p>The Alexa service is a great invention that is catching on. Google and Apple are dipping their toes into the market. I see the Star Trek experience in the home being a reality for everyone in a few years. Already my wife uses it (who swore she never would), and my 4 year old asks it to tell her jokes all the time. I use it to control my lights very often. The sky is the limit, and these tools can be useful in the workplace too. Get out there and build some neat stuff for Alexa with th [...]
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-03-introducing-grails-6-2-3.html'>
- <h3>January 3, 2025</h3>
- <h2>Introducing Grails Framework 6.2.3 Release</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-02-grails-community-rockstar-fredley.html'>
- <h3>January 2, 2025</h3>
- <h2>James Fredley Named 2025 Grails® Rock Star</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-06-26.html">https://grails.apache.org/blog/2016-06-26.html</a></p>
</body>
</html>
diff --git a/blog/2016-07-06.html b/blog/2016-07-06.html
index 0c10c337f4..b6dd940465 100644
--- a/blog/2016-07-06.html
+++ b/blog/2016-07-06.html
@@ -1,317 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Grails® Angular Scaffolding</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Lean how to use Grails provided scaffolding capabilities within an Angular application" />
- <meta name="date" content="July 6, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Lean how to use Grails provided scaffolding capabilities within an Angular application'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Grails® Angular Scaffolding'/>
- <meta property='og:description' content='Lean how to use Grails provided scaffolding capabilities within an Angular application'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-07-06.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Grails® Angular Scaffolding</h1>
-<p><span class="author">By James Kleeh</span></p>
-<p><span class="date">July 6, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/angular.html"><span class="hashtag">#angular</span></a></p>
-<p>Creating a single-page application (SPA) has never been easier than it is with the new <a href="https://github.com/grails-plugins/grails-angular-scaffolding">Grails<sup>®</sup> Angular Scaffolding Plugin</a>! This post will give you a short tutorial on how to use it.</p>
-<hr />
-<p>The easiest way to get started with the scaffolding is to use the angular profile in Grails 3.2.0 or higher, which installs and configures the plugin automatically. See the <a href="https://grails-plugins.github.io/grails-angular-scaffolding/latest">documentation</a> for information on how to get the plugin installed into an existing application.</p>
-<p>For this tutorial, we will be working with the following domain classes.</p>
-<pre><code class="language-groovy"> package com.myblog
-
- import grails.rest.Resource
-
- @Resource(uri="/post")
- class Post {
- URL url
- PostContent postContent
- static embedded = ['postContent']
- static hasMany = [comments: Comment , tags: Tag]
- static constraints = {
- }
- }
- //---------------------------------
- package com.myblog
-
- class PostContent {
- String title
- String body
- Date published
- static constraints = {
- }
- }
- //---------------------------------
- package com.myblog
-
- import grails.rest.Resource
-
- @Resource(uri="/tag")
- class Tag {
- String name
- static constraints = {
- }
- }
- //---------------------------------
- package com.myblog
-
- import grails.rest.Resource
-
- @Resource(uri="/comment")
- class Comment {
- String text
- static belongsTo = [post: Post]
- static constraints = {
- }
- }
-</code></pre>
-<h2>Generating Assets</h2>
-<p>Generating client-side assets with this plugin is very easy. In this example, the domain class you would like to have assets generated for is <code>com.myblog.Post</code>:</p>
-<pre><code> grails ngGenerateAll com.myblog.Post
-</code></pre>
-<p>To specify you wish any generated files to overwrite existing files:</p>
-<pre><code> grails ngGenerateAll com.myblog.Post true
-</code></pre>
-<p>You can also execute the same command with gradle:</p>
-<pre><code> ./gradlew ngGenerateAll -Pargs="com.myblog.Post true"
-</code></pre>
-<p>Some assets that are generated are common to all scaffolded modules. The scaffolding will generate those assets in the “core” module. The core module will be created in the same package as the module being generated if it doesn’t exist already.</p>
-<p>If a core module already exists, it will not be overwritten, even if the overwrite parameter is true.</p>
-<p>The following structure will be produced.</p>
-<p><img src="2016-07-06-img01.png" alt="Structure" /></p>
-<p>Note that other modules were created along with the post module.</p>
-<p>A module for the <code>Comment</code> domain was created because the scaffolding will convert the list of comments to be instances of the <code>Comment</code> JavaScript domain.</p>
-<p>The module for the <code>Tag</code> domain was also created by the scaffolding. The purpose of doing so is to facilitate retrieving a list of tags to choose from when creating a <code>Post</code>.</p>
-<p>The modules for the <code>Tag</code> and <code>Comment</code> domains do not provide CRUD functionality. They exist solely to assist the <code>Post</code> module.</p>
-<p>In the future, if you wish to scaffold the CRUD of <code>Tag</code>s or <code>Comment</code>s, execute the <code>ngGenerateAll</code> command with the second parameter set to “true” so the existing assets will be overwritten.</p>
-<h2>Using the Assets</h2>
-<p>If you are using the angular profile in Grails 3.2.0 or higher, none of the steps below are required because they are all done for you!</p>
-<p>If you are working with an existing application, there are a few steps you must take to make everything work together as designed.</p>
-<ol>
-<li>
-<p>Ensure that the required third-party libraries exist where the scaffolding expects them to be.</p>
-<p>The scaffolding requires angular, angular-resource, and ui-router to function as designed. The default locations for those assets are:</p>
-<ul>
-<li>/angular/angular.js</li>
-<li>/angular/angular-ui-router.js</li>
-<li>/angular/angular-resource.js</li>
-</ul>
-<p>You can change the default locations with configuration. See the <a href="https://grails-plugins.github.io/grails-angular-scaffolding/latest/#_asset_paths">asset paths</a> section in the documentation to learn how to do so.</p>
-</li>
-<li>
-<p>Ensure the required asset pipeline plugins have been imported.</p>
-<p>The scaffolding is designed around the use of three asset pipeline plugins. Include the plugins in your project via the instructions in the links below.</p>
-<ul>
-<li><a href="https://github.com/craigburke/angular-annotate-asset-pipeline">Angular Annotate Asset Pipeline</a></li>
-<li><a href="https://github.com/craigburke/angular-template-asset-pipeline">Angular Template Asset Pipeline</a></li>
-<li><a href="https://github.com/craigburke/js-closure-wrap-asset-pipeline">JS Closure Wrap Asset Pipeline</a></li>
-</ul>
-</li>
-<li>
-<p>Ensure databinding handles the default date format.</p>
-<p>The scaffolding relies on the default format Angular applies to dates when they are included in a request. In Grails 3.1.x, the date format is not included in the default list of date formats that databinding will attempt to use. You can easily add it yourself via configuration.</p>
-</li>
-</ol>
-<pre><code> grails:
- databinding:
- dateFormats:
- - "yyyy-MM-dd'T'HH:mm:ss.SSSX"
-</code></pre>
-<ol start="4">
-<li>
-<p>Ensure the module is loaded on the page</p>
-<p>If the "parent" module is already being required by your current code, there is nothing you need to do to get the newly generated module to be included wherever the parent module is. The scaffolding will automatically attempt to create a module dependency and require statement in the parent module.</p>
-<p>Here is an example of what that might look like.</p>
-</li>
-</ol>
-<pre><code> grails ngGenerateAll com.myblog.Post
-</code></pre>
-<pre><code>* If `grails-app/assets/javascripts/com/myblog/com.myblog.js` exists, it will be considered to be the parent module. The scaffolding will attempt to edit the file to add a dependency to the `post` module.
-
-If a parent module does not exist or the parent module isn’t being included on the desired page, it is up to you to use asset pipeline to include it where it is needed.
-</code></pre>
-<ol start="5">
-<li>
-<p>Ensure a <code>ui-view</code> directive is on the page for the state to load HTML into.</p>
-<p>See the ui-view [documentation](https://github.com/angular-ui/ui-router/wiki/Quick-Reference#ui-view target=) on how to do this.</p>
-</li>
-<li>
-<p>Ensure the <code>ng-app</code> directive is on the page. <code>ng-app="com.myblog.post"</code></p>
-</li>
-<li>
-<p>Naviage to the route <code>[http://localhost:8080/#post](http://localhost:8080/#post)</code></p>
-</li>
-</ol>
-<h2>CRUD</h2>
-<p>The following images depict what you will see when you have successfully navigated to the ‘post’ route and begin creating <code>Post</code>s.</p>
-<p>List
-<img src="2016-07-06-img02.png" alt="List" /></p>
-<p>Create
-<img src="2016-07-06-img03.png" alt="Create" /></p>
-<p>Note that clicking “Add Comment” at this time will not have any effect because the comment scaffolding has not been created.</p>
-<p>Show
-<img src="2016-07-06-img04.png" alt="Show" /></p>
-<h2>Generating Associated Domains</h2>
-<p>The logical next step will be to generate the <code>Tag</code> scaffolding so we can create tags. This will allow us to choose tags when creating or editing our <code>Post</code>.</p>
-<pre><code> grails ngGenerateAll com.myblog.Tag true
-</code></pre>
-<p>Note that the second parameter “true” is important because we already had a Tag module which we will need to overwrite in order for the scaffolding to function correctly.</p>
-<p>In addition, we can generate the comment scaffolding so we can assign comments to posts.</p>
-<pre><code> grails ngGenerateAll com.myblog.Comment true
-</code></pre>
-<p>The following are screen captures of what you can expect once the associated domain classes are generated.</p>
-<h3>Tag</h3>
-<p>Create
-<img src="2016-07-06-img05.png" alt="Create" /></p>
-<p>Show
-<img src="2016-07-06-img06.png" alt="Show" /></p>
-<p>List
-<img src="2016-07-06-img07.png" alt="List" /></p>
-<h3>Comment</h3>
-<p>Create
-<img src="2016-07-06-img08.png" alt="Create" /></p>
-<p>Show
-<img src="2016-07-06-img09.png" alt="Show" /></p>
-<p>List
-<img src="2016-07-06-img10.png" alt="List" /></p>
-<h2>Conclusion</h2>
-<p>Now that all domain classes have scaffolding, you can manage your data in a single page application.</p>
-<p>The scaffolding is designed as a starting point for rapid development. Explore the generated JavaScript code and make changes to meet your business requirements. If you run into any issues, please submit an issue on the github page <a href="https://github.com/grails-plugins/grails-angular-scaffolding/issues">here</a> or come chat with us about it in our <a href="https://grails.slack.com/">Slack</a> channel.</p>
-<p>For a complete run through of installing and using the scaffolding in Grails 3.1.x, check out this <a href="https://grails.org/blog/2017-01-20-2.html">Quickcast</a>!</p>
-<p>The example project created in the video is available <a href="https://github.com/grails-samples/angular-scaffolding-31x">here</a>.</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-03-introducing-grails-6-2-3.html'>
- <h3>January 3, 2025</h3>
- <h2>Introducing Grails Framework 6.2.3 Release</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2017-04-12.jpg)'>
- <a href='https://grails.org/blog/2017-04-12.html'>
- <h3>April 12, 2017</h3>
- <h2>Grails® Angular Profiles</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-07-06.html">https://grails.apache.org/blog/2016-07-06.html</a></p>
</body>
</html>
diff --git a/blog/2016-07-22.html b/blog/2016-07-22.html
index 784343aea8..90a5d28503 100644
--- a/blog/2016-07-22.html
+++ b/blog/2016-07-22.html
@@ -1,173 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Grails® 3.2 M2 and GORM 6.0 M2 Released</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Grails 3.2. M2 and GORM 6.0 M2 release announcement" />
- <meta name="date" content="July 22, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Grails 3.2. M2 and GORM 6.0 M2 release announcement'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Grails® 3.2 M2 and GORM 6.0 M2 Released'/>
- <meta property='og:description' content='Grails 3.2. M2 and GORM 6.0 M2 release announcement'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-07-22.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Grails® 3.2 M2 and GORM 6.0 M2 Released</h1>
-<p><span class="author">By Graeme Rocher</span></p>
-<p><span class="date">July 22, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/release.html"><span class="hashtag">#release</span></a></p>
-<p>Today the <a href="https://objectcomputing.com/products/2gm-team">Grails team</a> at <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) is pleased to announce the release of <a href="https://github.com/grails/grails-core/releases/tag/v3.2.0.M2">Grails<sup>®</sup> 3.2 Milestone 2</a>, which includes <a href="https://gorm.grails.org/6.0.x">GORM 6 Milestone 2</a> - the biggest GORM release ever!</p>
-<p>The <a href="https://gorm.grails.org/6.0.x">new version of GORM</a> is really the theme of this release. There are so many great new features that we wrote a dedicated <a href="https://gorm.grails.org/6.0.x/whatsNew/manual/index.html">"What's New"</a> guide just for GORM (to go along with the new dedicated GORM documentation).</p>
-<p>Just to summarize the new features in GORM include:</p>
-<ul>
-<li><a href="https://gorm.grails.org/6.0.x/neo4j/manual/index.html">GORM for Neo4j</a> 3.0 Bolt Driver Support</li>
-<li><a href="https://gorm.grails.org/6.0.x/mongodb/manual/index.html">GORM for MongoDB</a> 3.2 Drivers</li>
-<li><a href="https://gorm.grails.org/6.0.x/rx/manual/index.html">RxGORM - GORM for RxJava</a></li>
-<li><a href="https://gorm.grails.org/1.0.x/rx/rest-client/manual">RxGORM for REST</a> built on RxNetty</li>
-<li><a href="https://gorm.grails.org/6.0.x/rx/manual/index.html">RxGORM for MongoDB</a> built on the MongoDB Rx Driver</li>
-<li><a href="https://gorm.grails.org/6.0.x/hibernate/manual/index.html#multipleDataSources">Universal Multiple Data Sources Support</a> includin a new <a href="https://gorm.grails.org/6.0.x/hibernate/manual/index.html#connectionSources">ConnectionSources API</a></li>
-<li><a href="https://gorm.grails.org/6.0.x/hibernate/manual/index.html#multiTenancy">Multi Tenancy Support</a> for Hibernate, MongoDB and Neo4j</li>
-<li><a href="https://gorm.grails.org/6.0.x/hibernate/manual/index.html#outsideGrails">Spring Container Free Bootstrapping</a></li>
-<li><a href="https://gorm.grails.org/6.0.x/hibernate/manual/index.html#configuration">Unified Configuration API</a></li>
-<li><a href="https://gorm.grails.org/6.0.x/hibernate/manual/index.html#testing">Improved Unit Testing</a></li>
-</ul>
-<p>Of course GORM 6.0 is usable in all versions of Grails 3.x.</p>
-<p>On the Grails side, Grails 3.2 ships with release candidates of the new AngularJS 1.0 scaffolding (Angular 2.0 support is coming) and JSON Views 1.1 plugins as well as numerous improvements to the profiles.</p>
-<p>Grails 3.2 has also been updated to the latest and greatest dependencies including Spring Boot 1.4 RC1 and Spring 4.3.</p>
-<p>Check out the <a href="https://docs.grails.org/3.2.x/guide/introduction.html#whatsNew">What's New in Grails 3.2 Guide</a> for information on all the updates.</p>
-<p>We're inching closer to an RC now so it is a great time to try your applications and <a href="https://github.com/grails/grails-core/issues">report issues</a>!</p>
-<p>If you want to hear more come and see us at Gr8Conf US in Minneapolis USA, or G3 Summit in Fort Lauderdale USA!</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2019-07-11.jpg)'>
- <a href='https://grails.org/blog/2019-07-11.html'>
- <h3>July 11, 2019</h3>
- <h2>Grails® 4 GA Released</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2019-02-19.jpg)'>
- <a href='https://grails.org/blog/2019-02-19.html'>
- <h3>February 19, 2019</h3>
- <h2>Grails® 4 Milestone 1 Released</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2017-07-26.jpg)'>
- <a href='https://grails.org/blog/2017-07-26.html'>
- <h3>July 26, 2017</h3>
- <h2>Grails® 3.3 GA Released</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-07-22.html">https://grails.apache.org/blog/2016-07-22.html</a></p>
</body>
</html>
diff --git a/blog/2016-08-01.html b/blog/2016-08-01.html
index 7c9cb0d360..b4df873de6 100644
--- a/blog/2016-08-01.html
+++ b/blog/2016-08-01.html
@@ -1,228 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>GR8Conf US 2016 Wrap-up!</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="GR8Conf US 2016 Wrap-up!" />
- <meta name="date" content="August 1, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='GR8Conf US 2016 Wrap-up!'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='GR8Conf US 2016 Wrap-up!'/>
- <meta property='og:description' content='GR8Conf US 2016 Wrap-up!'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-08-01.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>GR8Conf US 2016 Wrap-up!</h1>
-<p><span class="author">By Ryan Vanderwerf</span></p>
-<p><span class="date">August 1, 2016</span></p>
-<p><img src="2016-08-01-img01.png" alt="The OCI Grails® team at GR8Conf US 2016" /></p>
-<p>Well I've just started to clear my fuzzy head getting back from <a href="https://gr8conf.us/">GR8Conf US</a> in Minneapolis, where OCI was a platinum sponsor this year. Lots of good stuff came out of the show, things announced, good workshops. There were 4 concurrent tracks of talks for 2 days, and 1 day of workshops. In all, the OCI Grails team delivered 4 workshops and 8 talks - most of the team creates these talks on their own time as well in addition to our regular responsibilitie [...]
-<p><img src="2016-08-01-img02.jpg" alt="" /></p>
-<p>I grew up in a suburb in St. Paul and had not been back since I started speaking at Gr8Conf 3-4 years ago. What a beautiful city it is now! So much stuff going on, sports games, music, breweries and a pretty clean downtown. Can't recommend enough to come visit here in the summer - that said I would avoid it in the thick of winter - it's so cold they build sky-bridges to connect the buildings to minimize the outside elements! Check out one of these great buildings at night. The picture [...]
-<p><img src="2016-08-01-img03.png" alt="Skyline" /></p>
-<h2>Day 1: Workshops</h2>
-<p><img src="2016-08-01-img04.jpg" alt="Ryan and Lee presenting Alexa, Tell Me I'm Groovy" /></p>
-<p>I started the day doing my Groovy Lego Mindstorms EV3 talk where we worked with putting Groovy apps on the robots, then used the Grails framework to control the robots like Mars rovers. I Then did a 2nd half day workshop with my friend Lee Fox on Amazon Alexa. We built Groovy Lambda Skills as well as Grails 3 Skills.</p>
-<p><img src="2016-08-01-img05.jpeg" alt="Jeff Scott Brown presenting at GR8Conf US 2016" /></p>
-<p>Jeff Brown then did 2(!) back-to-back workshops on 'Getting Started with Grails 3' and 'Rest with Grails 3' (*Pic by Annyce Davis).</p>
-<p>Danny Hyun did a Groovy intro workshop where he taught people to use a Pokemon Java API to help them catch them all in Groovy (all day).
-Marcin Erdmann (His first stateside appearance at Gr8?) did an all day Ratpack sandbox workshop.</p>
-<h2>Day 2: Talks</h2>
-<p><img src="2016-08-01-img06.jpg" alt="Graeme Rocher presenting the keynote presentation" /></p>
-<p>Graeme Rocher kicked off the conference with his keynote about all the goodness upcoming in Grails 3.2, GORM 6, and how overall better things are about Grails 3 as well as the future.</p>
-<p>Here we start the 4 parallel tracks, with one being 'Groovy for Java Developers' by Puneet Behl where he teaches how Groovy makes life better for Java devs.</p>
-<p>In the same slots were "Getting Started with Grails 3" by OCI Grails team member Colin Harrington gave a great Grails 3 intro talk.</p>
-<p>Also there was "GroovyFX - Groove JavaFX" by Alexander Sasha Klein on all the goodies aroung GroovyFX.</p>
-<p>Next up: Dynamic GORM by Burt Beckwith, Monitoring and Metrics with Grails 3 by OCI Grails Team co-founder Jeff Scott Brown. Craig Burke always brings the laughs with "Practical and Stupidly Impractical Groovy DSLs. Android Groovy plugin maintainer Andrew Reitz did a good talk on testing Gradle plugins, which is something people often overlook but is needed.</p>
-<p><img src="2016-08-01-img07.jpeg" alt="Ryan and Lee presenting Alexa, Tell Me I'm Groovy Day 2" /></p>
-<p>Next slot after lunch: Lee Fox and I do the "Alexa Tell me I'm Groovy" talk which we covered AWS Groovy Lambda Skills and The Grails 3 plugin. Lee made a superhero quiz game and Baruch from JFrog stepped up to test his skills. Needless to say he said his name and Alexa said 'I heard bottles' and proceeded to ask 'Bottles' trivia questions. So that is Baruch's new nickname, try it out next time you see him :) The audience got lots of laughs from all the Alexa antics we did. I [...]
-<p>While this was going on fellow OCI Grails team member Alvaro Sanchez-Mariscal did 'Mastering Grails 3 Plugins' with some solid advice on Grails 3 to avoid pain later. Asset-pipeline creator Dave Estes did a great talk on the ins and outs of asset-pipeline which every Grails developer should learn and know. Finishing this slot is Jenn Strater's talk on a TDD Approach to Documenting Restful APIs which a lot of people were excited about all of the documentation tools she showed off.</p>
-<p>Last talk slot of the day:</p>
-<p>Bob the Builder by Sascha Klein shared his tips of using builder patterns for daily survival. Teammate Alvaro continued with another talk on Creating apps with the Grails framework, AngularJS, and Spring Security which is a shorter talk version of the workshop he did at Gr8Conf.eu this year. Annyce Davis a new speaker I met this year did a great talk on From the Grails framework to Android: A Simple Journey. Finishing the talks for the day was Jenn Strater with "CodeNarc Revisite [...]
-<p><img src="2016-08-01-img08.jpeg" alt="Alvaro presenting on Grails, Angular, and DDS" /></p>
-<p>Kenneth Kousen closed up the day with a great keynote that talked about all the value Groovy and all the community has to offer.</p>
-<p><img src="2016-08-01-img09.jpeg" alt="Ken Kousen delivering a keynote at GR8Conf US 2016" /></p>
-<p>After the talks and keynote, Object Partners was kind enough to bus everyone to their new offices in North Minneapolis for Gr8ConfUS beer, appetizers, and Groovy Puzzlers with Baruch(Bottles) and Dan Woods.</p>
-<p><img src="2016-08-01-img10.jpeg" alt="Groovy Puzzlers with Baruch(Bottles) and Dan Woods" /></p>
-<p><img src="2016-08-01-img11.jpeg" alt="Gr8ConfUS Beer" /></p>
-<h2>Day 3 Talks</h2>
-<p>We roll into day 3 running with (almost) a complete track of talks about Ratpack by Dan Woods (9am after late night karaoke, impressive!), non web Ratpack with John Engelman, and testing Rackpack with Danny Hyun. Back to chronological order, Puneet Behl talked about Giving back to the community by helping migrate 2.x plugins to 3.x. Annyce David talked about Gradle Plugin Goodness, and Ryan Applegate talked about scaling Grails apps at SmartThings.</p>
-<p>Craig Burke talked about AngularJS in Grails apps as well as trolled Kyle Boon and myself pretty hard (His test is totally rigged I say!). Jeff Brown from OCI Grails Team talked about Groovy Metaprogramming, and Charlie Knudsen talked about a strategy to get to zero downtime deployments.</p>
-<p><img src="2016-08-01-img12.jpeg" alt="Colin Harrington's presentation about how to secure your Grails application via Spring Security Plugins" /></p>
-<p>Next slot we had fellow OCI Grails teammate Colin Harrington talk about how to secure your Grails application via Spring Security Plugins. Sacha Klein also gave a Groovy with Jenkins talk about using Groovy in your CI pipeline. Todd Miller talked about Spring Cloud in production with tools like Eureka and Hystrix/Turbine to monitor your apps. Craig Atkinson also gave a great Spock and Geb into talk.</p>
-<p>After lunch Burt Beckwith talked about Spring Security, Christian Oestreich talked about monitoring Grails 3 applications, Craig Atkinson gave another great functional testing talk with Geb. Stephen Pember gave a mind-bender talk on Reactive Streams and Groovy to finish out the time slot.</p>
-<p>Last talks of the day are now underway with "Grails Reactive Event-Driven Architecture" by Christian Oestreich (He maintains several Grails plugins like CXF/Client), Dockerize It All by Puneet Behl, and last but not least a JOOQ intro talk by Stephen Pember.</p>
-<p>Wrapping up the conference, John Engelman gave the closing keynote about writing software in the Agile age, culture devops, and other good stuff.</p>
-<p>After that, Ken Kousen and Baruch(Bottles) Sadogursky did a live Groovy podcast with a studio audience!. The link for it is <a href="https://www.youtube.com/watch?v=MWRWnKfbnIs">here</a>.</p>
-<p><img src="2016-08-01-img13.jpeg" alt="Gr8Ladies-sponsored happy hour" /></p>
-<p>Once the broadcast concluded, most of the attendees went home, but many speakers and attendees stayed and went to the Gr8Ladies sponsored happy hour. That extended to the roof later, where the Ratpack folks really showed their dance moves, especially Danny Hyun!</p>
-<p><img src="2016-08-01-img14.png" alt="Ratpack folks showing off their dance moves, especially Danny Hyun" /></p>
-<p>Special thanks to out to all the volunteers and helpers for the conference, especially Bobby Warner, Shaun Jurgenmeyer, Eric Kinsella, Doug Sabers, and Jenn Strater!</p>
-<p>I hope to be back again next year, as you won't find a nicer, friendlier accessible bunch than the folks at the Gr8Conf conferences. Come for the content, stay for the socialization and networking! The more I go to these events, I find the value scale for networking goes higher and higher, which is something you just can't get off youtube videos and posted slides. Come to see what others are doing or not doing because it didn't work - It could save your next project from failure!</p>
-<hr />
-<h2>Slide Decks From the Conference</h2>
-<p>(cobbled together and ripped from tweets and Grails Diary)</p>
-<h3>Workshops</h3>
-<p><a href="https://www.dropbox.com/sh/ah2uxd9he0x4p4f/AACGHZEiY-PP9Zl3qpLCI4XOa?dl=0">Exercises for Getting started with Grails 3 (Jeff Scott Brown)</a></p>
-<p><a href="https://www.slideshare.net/ryanvanderwerf/getting-groovy-with-lego-mindstorms-ev3-gr8conf-us-2016">Getting Groovy with Lego Mindstorms (Ryan Vanderwerf)</a></p>
-<p><a href="https://www.slideshare.net/ryanvanderwerf/amazon-alexa-workshop-grpovy-and-grails-gr8conf-us-2016">Amazon Alexa Workshop (Ryan Vanderwerf and Lee Fox</a> also labs <a href="https://sites.google.com/site/alexaskillslab/">here</a></p>
-<p><a href="https://danhyun.github.io/2016-gr8conf-groovy-workshop/">Groovy Workshop 2016 (Daniel Hyun)</a></p>
-<h3>Talks – Day 2</h3>
-<p><a href="https://slides.com/colinharrington/getting-started-with-grails-3-gr8confus-2016#/">Getting started with Grails 3 (Colin Harrington)</a></p>
-<p><a href="http://www.craigburke.com/practical-groovy-dsl/">Practical and Stupidly Impractical Groovy DSLs (Code) (Craig Burke)</a></p>
-<p><a href="https://speakerdeck.com/rvanderwerf/alexa-tell-me-im-groovy-gr8conf-us-2016">Alexa, Tell Me I'm Groovy (Ryan Vanderwerf / Lee Fox)</a></p>
-<p><a href="https://www.slideshare.net/alvarosanchezmariscal/mastering-grails-3-plugins-gr8conf-us-2016">Mastering Grails 3 plugins (Alvaro Sanchez-Mariscal)</a></p>
-<p><a href="https://speakerdeck.com/jlstrater/codenarc-revisited-gr8conf-us-2016">Codenarc Revisited (Jenn Strater)</a></p>
-<p><a href="https://www.adavis.info/2016/07/talk-from-grails-to-android.html">From Grails to Android (Annyce Davis)</a></p>
-<p><a href="https://speakerdeck.com/jlstrater/a-test-driven-approach-to-documenting-restful-apis-with-spring-rest-docs-gr8conf-us">A Test-Driven Approach to Documenting RESTful APIs with Spring REST Docs (Jenn Strater)</a></p>
-<h3>Talks – Day 3</h3>
-<p><a href="https://slides.com/colinharrington/springsecuritysurvey-gr8conf-us-2016#/">Securing your Grails application: A survey/layout of the security plugin space (Colin Harrington)</a></p>
-<p><a href="https://speakerdeck.com/rappleg/scaling-grails-at-smartthings">Scaling Grails at SmartThings (Ryan Applegate)</a></p>
-<p><a href="https://www.adavis.info/2016/07/talk-gradle-plugin-goodness.html">Gradle Plugin Goodness (Annyce Davis)</a></p>
-<p><a href="https://www.slideshare.net/alvarosanchezmariscal/creating-applications-with-grails-angular-js-and-spring-security-gr8conf-us-2016">Creating applications with Grails, Angular JS and Spring Security - (code) (Alvaro Sanchez-Mariscal)</a></p>
-<p><a href="https://craigatk.github.io/spock-geb-intro/">Intro to Spock and Geb (Craig Atkinson)</a></p>
-<p><a href="https://github.com/Grails-Plugin-Consortium/gr8conf-monitoring-metrics">Monitoring Grails 3 Applications (Christian Oestreich)</a></p>
-<p><a href="https://github.com/Grails-Plugin-Consortium/gr8conf-event-driven-microservices">Grails Reactive Event-Driven Architecture (Christian Oestreich)</a></p>
-<p><a href="https://craigatk.github.io/geb-tips-tricks/#/">Geb Tips and Tricks (Craig Atkinson)</a></p>
-<p><a href="https://danhyun.github.io/2016-gr8confus-testing-ratpack-apps/">Testing Ratpack Applications (Danny Hyun)</a></p>
-<p><a href="https://www.slideshare.net/StevePember/reactive-streams-and-the-wide-world-of-groovy-64526341">Reactive Streams and the Wide World of Groovy (Steve Pember)</a></p>
-<p><a href="https://www.slideshare.net/StevePember/an-introduction-to-jooq">An Introduction to jOOQ - code (Steve Pember)</a></p>
-<h3>Some Other Recaps</h3>
-<p><a href="https://www.adavis.info/2016/07/gr8conf-us-2016-recap.html">Annyce Davis</a></p>
-<p><a href="https://rpalcolea.github.io/blog/2016/GR8Conf-US-Recap-2016.html">Roberto Perez A.</a></p>
-<p>I look forward to the next edition in 2017!</p>
-<p>— Ryan Vanderwerf and the rest of the OCI/Grails Team</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-03-introducing-grails-6-2-3.html'>
- <h3>January 3, 2025</h3>
- <h2>Introducing Grails Framework 6.2.3 Release</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-02-grails-community-rockstar-fredley.html'>
- <h3>January 2, 2025</h3>
- <h2>James Fredley Named 2025 Grails® Rock Star</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-08-01.html">https://grails.apache.org/blog/2016-08-01.html</a></p>
</body>
</html>
diff --git a/blog/2016-08-31.html b/blog/2016-08-31.html
index 8a6474a440..fb35d211f6 100644
--- a/blog/2016-08-31.html
+++ b/blog/2016-08-31.html
@@ -1,284 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Retrieving Config Values In Grails® 3</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Retrieving Config Values In Grails 3" />
- <meta name="date" content="August 31, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Retrieving Config Values In Grails 3'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Retrieving Config Values In Grails® 3'/>
- <meta property='og:description' content='Retrieving Config Values In Grails 3'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-08-31.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Retrieving Config Values In Grails® 3</h1>
-<p><span class="author">By Jeff Scott Brown</span></p>
-<p><span class="date">August 31, 2016</span></p>
-<h2>Introduction</h2>
-<p>The Grails<sup>®</sup> framework leverages the “Convention Over Configuration” design paradigm, which functions to decrease the number of decisions that a developer using the framework is required to make without losing flexibility. This is one of the ways Grails significantly increases developer productivity!</p>
-<p>While Grails applications often involve considerably less configuration than similar applications built with other frameworks, some configuration may still be necessary. This post will detail a number of mechanisms that make it easy for Grails developers gain access to those configuration values at runtime.</p>
-<h3>application.yml</h3>
-<p>The default configuration file for Grails 3 applications is <code>grails-app/conf/application.yml</code>. In this file, <a href="https://yaml.org/">YAML</a> syntax is supported.</p>
-<pre><code class="language-yaml">dataSource:
- pooled: true
- jmxExport: true
- driverClassName: org.h2.Driver
-</code></pre>
-<p>That file defines 3 configuration properties.</p>
-<pre><code class="language-plaintext">dataSource.pooled = true
-dataSource.jmxExport = true
-dataSource.driverClassName = 'org.h2.Driver'
-</code></pre>
-<p>This article will not go into detail about YAML syntax. For that see <a href="https://yaml.org/">the main YAML site</a>. Instead, this article will focus on Grails 3 specific features related to accessing those configuration values.</p>
-<h2>The Config Property in GrailsApplication</h2>
-<p>The <a href="https://docs.grails.org/3.1.10/api/grails/core/GrailsApplication.html">GrailsApplication</a> interface defines the <a href="https://docs.grails.org/3.1.10/api/grails/core/GrailsApplication.html#getConfig()">getConfig</a> method which returns a <a href="https://docs.grails.org/3.1.10/api/grails/config/Config.html">Config</a> object. In the Spring application context is a bean named <code>grailsApplication</code> which is an instance of a class which implements the <code>Gr [...]
-<pre><code class="language-yaml"># grails-app/conf/application.yml
-max:
- line:
- numbers: 42
-</code></pre>
-<pre><code class="language-groovy">// grails-app/init/BootStrap.groovy
-
-import grails.core.GrailsApplication
-
-class BootStrap {
-
- // this property will be auto-wired from
- // the Spring application context...
- GrailsApplication grailsApplication
-
- def init = { servletContext ->
- // retrieve the max.line.numbers config value
- def maxLineNumbers = grailsApplication.config.getProperty('max.line.numbers')
-
- // ...
-
- }
-}
-</code></pre>
-<blockquote>
-<p>NOTE: <code>config.getProperty('max.line.numbers')</code> is preferred over something like <code>config.max.line.numbers</code>. The latter can result in unexpected behavior when retrieving values that do not exist and also is less performant.</p>
-</blockquote>
-<h3>Type Conversions</h3>
-<p>There is an overloaded version of the <code>getProperty</code> method that accepts a type. This overloaded method will convert the corresponding config value to the specified type.</p>
-<pre><code class="language-groovy">// retrieve the max.line.numbers config value
-// returns null if the config value does not
-// exist or if the type conversion fails
-Integer maxLineNumbers = config.getProperty('max.line.numbers', Integer)
-</code></pre>
-<h3>Default Values</h3>
-<p>There is another overloaded version of the <code>getProperty</code> method which accepts both a type and a default value.</p>
-<pre><code class="language-groovy">// retrieve the max.line.numbers config value
-// returns 2112 if the config value does not
-// exist or if the type conversion fails
-Integer maxLineNumbers = config.getProperty('max.line.numbers', Integer, 2112)
-</code></pre>
-<h3>Required Properties</h3>
-<p>For required properties you could write application code that reacts however is appropriate if the property doesn't exist. You could also use the <a href="https://docs.grails.org/3.1.10/api/grails/config/ConfigMap.html#getRequiredProperty(java.lang.String,%20java.lang.Class)">getRequiredProperty</a> method which will throw an exception if a requested property does not exist.</p>
-<pre><code class="language-groovy">// retrieve the max.line.numbers config value
-// throws IllegalStateException if the
-// config value does not exist
-Integer maxLineNumbers = config.getRequiredProperty('max.line.numbers', Integer)
-</code></pre>
-<h2>Config Dependency Injection</h2>
-<p>For config values that are needed during request processing, an application may want to retrieve the value only once instead of retrieving it repeatedly during each request that requires access to the config value. For example, the following is not ideal because the application is paying the performance price of retrieving the config value every time the controller action is invoked.</p>
-<pre><code class="language-groovy">import grails.config.Config
-
-class SomeController {
-
- def someAction() {
- Config config = grailsApplication.config
- // this would happen for every request to this action...
- int maxLineNumbers = config.getProperty('max.line.numbers', Integer, 10)
-
- // ...
- }
-}
-</code></pre>
-<h3>Config Injection Using GrailsConfigurationAware</h3>
-<p>An alternative is to retrieve the config value only once and then hold on to it so that it may be used later as many times as necessary. One way to do this is to have the config injected into any bean by implementing the <a href="https://docs.grails.org/3.1.10/api/grails/core/support/GrailsConfigurationAware.html">GrailsConfigurationAware</a> interface. There is a bean post processor that will discover all beans that implement at that interface and that post processor will invoke the [...]
-<pre><code class="language-groovy">import grails.config.Config
-import grails.core.support.GrailsConfigurationAware
-
-class WidgetService implements GrailsConfigurationAware {
-
- int area
-
- def someServiceMethod() {
- // this method may use the area property...
- }
-
- @Override
- void setConfiguration(Config co) {
- int width = co.getProperty('widget.width', Integer, 10)
- int height = co.getProperty('widget.height', Integer, 10)
- area = width * height
- }
-}
-</code></pre>
-<h3>Config Injection Using @Value</h3>
-<p>Another option for injecting config values is to use the <a href="https://docs.spring.io/spring/docs/4.2.6.RELEASE/javadoc-api/org/springframework/beans/factory/annotation/Value.html">@Value</a> annotation.</p>
-<pre><code class="language-groovy">import org.springframework.beans.factory.annotation.Value
-
-class WidgetService {
-
- int area
-
- @Value('${widget.width}')
- int width
-
- def someServiceMethod() {
- // this method may use the width property...
- }
-}
-</code></pre>
-<p>In the example above, an exception will be thrown if the <code>widget.width</code> config value does not exist. In order to provide a default value with the <code>@Value</code> annotation, provide the default value after a <code>:</code> in the expression supplied to the annotation.</p>
-<pre><code class="language-groovy">import org.springframework.beans.factory.annotation.Value
-
-class WidgetService {
-
- @Value('${widget.width:50}')
- int width
-
- def someServiceMethod() {
- // this method may use the area property...
- }
-}
-</code></pre>
-<h2>Conclusion</h2>
-<p>The examples above detail several approaches for retrieving config values at runtime. Grails intentionally provides several options, each with its own strengths and flexibility. Knowing where and when config values need to be accessible will help dictate which approach makes the most sense for a particular use case.</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-03-introducing-grails-6-2-3.html'>
- <h3>January 3, 2025</h3>
- <h2>Introducing Grails Framework 6.2.3 Release</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-02-grails-community-rockstar-fredley.html'>
- <h3>January 2, 2025</h3>
- <h2>James Fredley Named 2025 Grails® Rock Star</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-08-31.html">https://grails.apache.org/blog/2016-08-31.html</a></p>
</body>
</html>
diff --git a/blog/2016-09-12.html b/blog/2016-09-12.html
index 7867ce32c3..ec6e647c3c 100644
--- a/blog/2016-09-12.html
+++ b/blog/2016-09-12.html
@@ -1,291 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>How to Migrate from Resources Plugin to Asset-Pipeline</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Migrate from resources plugin to asset-pipeline in the Grails® framework" />
- <meta name="date" content="September 12, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Migrate from resources plugin to asset-pipeline in the Grails® framework'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='How to Migrate from Resources Plugin to Asset-Pipeline'/>
- <meta property='og:description' content='Migrate from resources plugin to asset-pipeline in the Grails® framework'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-09-12.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>How to Migrate from Resources Plugin to Asset-Pipeline</h1>
-<p><span class="author">By Iván López</span></p>
-<p><span class="date">September 12, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/plugins.html"><span class="hashtag">#plugins</span></a></p>
-<h2>Introduction</h2>
-<p>Since Grails<sup>®</sup> 2.4.0, <a href="https://grails.org/plugin/asset-pipeline">asset-pipeline</a> has been the default plugin recommended to manage the static resources in a Grails application. In earlier versions of the Grails framework, the <a href="https://github.com/grails-plugins/grails-resources">resources</a> plugin was an option, but with Grails 3, the only viable option is using asset-pipeline because resources is not available in Grails 3.</p>
-<p>If you want to know how to migrate from resources to asset-pipeline, this post is for you.</p>
-<h2>Let's Migrate!</h2>
-<p>I recommend you start the migration analyzing your layouts because probably those files contain most of your static resources (javascripts and css files). Imagine that the content of your <code>main.gsp</code> layout is the following:</p>
-<pre><code class="language-html"><link rel="stylesheet" href="${resource(dir: 'assets/css', file:'bootstrap.min.css') }" />
-<link rel="stylesheet" href="${resource(dir: 'assets/css', file:'jquery-ui-1.10.3.full.min.css') }" />
-<link rel="stylesheet" href="${resource(dir: 'assets/css', file:'jquery-ui-1.10.3.custom.min.css') }" />
-<link rel="stylesheet" href="${resource(dir: 'assets/css', file:'jquery.gritter.css') }" />
-<link rel="stylesheet" href="${resource(dir: 'assets/css', file:'ui.jqgrid.css') }" />
-
-<script src="${resource(dir:'assets/js', file:'bootstrap.min.js')}"></script>
-<script src="${resource(dir:'assets/js', file:'jquery-2.0.3.min.js')}"></script>
-<script src="${resource(dir:'assets/js', file:'jquery-ui-1.10.3.custom.min.js') }"></script>
-<script src="${resource(dir:'assets/js', file:'jquery-ui-1.10.3.full.min.js') }"></script>
-<script src="${resource(dir:'assets/js', file:'jquery.mobile.custom.min.js')}"></script>
-<script src="${resource(dir:'assets/js', file:'jquery.slimscroll.min.js')}"></script>
-<script src="${resource(dir:'assets/js', file:'jquery.gritter.min.js')}"></script>
-<script src="${resource(dir:'assets/js', file:'jquery.hotkeys.min.js')}"></script>
-<script src="${resource(dir:'assets/js', file:'jquery.easy-pie-chart.min.js')}"></script>
-<script src="${resource(dir:'assets/js', file:'jquery.maskedinput.min.js')}"></script>
-<script src="${resource(dir:'assets/js', file:'jquery.dataTables.min.js')}"></script>
-<script src="${resource(dir:'assets/js', file:'jquery.dataTables.bootstrap.js')}"></script>
-<script src="${resource(dir:'assets/js/jqGrid', file:'jquery.jqGrid.min.js')}"></script>
-<script src="${resource(dir:'assets/js/jqGrid/i18n', file:'grid.locale-en.js')}"></script>
-</code></pre>
-<p>As you can see, there are a bunch of css and javascript files that are mostly related to jQuery, but all of those files are on the same directory. When doing the migration, we're also going to reorganize the files in a better way.</p>
-<p>By default, asset-pipeline creates the directories <code>images</code>, <code>javascripts</code>, and <code>stylesheets</code> under <code>grails-app/assets</code> directory. Any file you copy into those directories can be served by the plugin. The easy way would be to copy all of the css and javascript files to those directories and change the way we import the resources.</p>
-<p>For example, with the following directory structure:</p>
-<pre><code class="language-bash">.
-├── javascripts
-│ └── bootstrap.min.js
-└── stylesheets
- └── bootstrap.min.css
-</code></pre>
-<p>You could replace the following code:</p>
-<pre><code class="language-html"><!-- Using resources -->
-<link rel="stylesheet" href="${resource(dir: 'assets/css', file:'bootstrap.min.css') }" />
-<script src="${resource(dir:'assets/js', file:'bootstrap.min.js')}"></script>
-</code></pre>
-<p>With this one:</p>
-<pre><code class="language-html"><!-- Using asset-pipeline -->
-<asset:stylesheet src="bootstrap.min" ></asset:stylesheet>
-<asset:javascript src="bootstrap.min" ></asset:javascript>
-</code></pre>
-<p>Please notice that you don't need to include the <code>.js</code> or <code>.css</code> extension because asset-pipeline will add it when looking for the files in those directories.</p>
-<p>As I said, you could just copy all those files and create a lot of entries in your layout using <code>asset:stylesheet</code> and <code>asset:javascript</code>, but we can do it better.</p>
-<h2>Defining Bundles</h2>
-<p>If you take a look at the content of the <code>grails-app/assets</code> directory created by default, you can find the files <code>application.js</code> and <code>aplication.css</code>.</p>
-<p>Let's take a look at the content of the <code>application.css</code> file:</p>
-<pre><code class="language-css">/*
-* This is a manifest file that'll be compiled into application.css, which will include all the files
-* listed below.
-*
-* Any CSS file within this directory can be referenced here using a relative path.
-*
-* You're free to add application-wide styles to this file and they'll appear at the top of the
-* compiled file, but it's generally better to create a new file per style scope.
-*
-*= require bootstrap
-*= require grails
-*= require main
-*= require mobile
-*= require_self
-*/
-</code></pre>
-<p>We're defining a bundle called <code>application</code> (the name of the file) that will contain <code>bootstrap</code>, <code>grails</code>, <code>main</code>, and <code>mobile</code> stylesheet files. Starting with that we're going to add the rest of the original files we were using with resources plugin:</p>
-<pre><code class="language-css">/*
-*= require bootstrap.min
-*= require jquery/css/jquery-ui-1.10.3.full.min
-*= require jquery/css/jquery-ui-1.10.3.custom.min
-*= require jquery/css/jquery.gritter
-*= require jqGrid/ui.jqgrid
-*/
-</code></pre>
-<p>You can create arbitrary bundles of your js and css files, defining files in the root of those directories and declaring the files you want to add to that bundle. Now we're going the create a bundle for the javascript files:</p>
-<pre><code class="language-javascript">//
-// require bootstrap.min
-//= require jquery/js/jquery-2.0.3.min
-//= require jquery/js/jquery-ui-1.10.3.custom.min
-//= require jquery/js/jquery-ui-1.10.3.full.min
-//= require jquery/js/jquery.mobile.custom.min
-//= require jquery/js/jquery.slimscroll.min
-//= require jquery/js/jquery.gritter.min
-//= require jquery/js/jquery.hotkeys.min
-//= require jquery/js/jquery.easy-pie-chart.min
-//= require jquery/js/jquery.maskedinput.min
-//= require jquery/js/jquery.dataTables.min
-//= require jquery/js/jquery.dataTables.bootstrap
-
-//= require jqGrid/jquery.jqGrid.min
-//= require jqGrid/i18n/grid.locale-en
-</code></pre>
-<p>With these two bundles defined, the only thing you need to do is replace all those javascript and stylesheet imports in your layout with the following lines:</p>
-<pre><code class="language-html"><asset:stylesheet src="application" ></asset:stylesheet>
-<asset:javascript src="application" ></asset:javascript>
-</code></pre>
-<p>Now we can run the application, open the inspector and see what happens:</p>
-<p><img src="2016-09-12-img01.jpg" alt="Javascripts" /></p>
-<p><img src="2016-09-12-img02.jpg" alt="Stylesheets" /></p>
-<p>All the javascript and css files are loaded in debug mode. This means that the resources won't be optimized and you'll have hot-reloading of the changes. This is the default behavior during development. For production all files will be minified and included in one file per bundle:</p>
-<p><img src="2016-09-12-img03.jpg" alt="assets-minifies-prod" /></p>
-<h2>Organizing Bundles</h2>
-<p>One last thing about organizing the bundles is that if we want to create our custom directories, we need to create a top level directory in <code>grails-app/assets</code>, and inside that directory, we can create our arbitrary structure. I've named this directory <code>libs</code>, but you can use the name you want:</p>
-<pre><code class="language-bash">.
-├── javascripts
-│ ├── application.js
-│ └── bootstrap.min.js
-├── libs
-│ ├── jqGrid
-│ │ ├── i18n
-│ │ │ └── grid.locale-en.js
-│ │ ├── jquery.jqGrid.min.js
-│ │ └── ui.jqgrid.css
-│ └── jquery
-│ ├── css
-│ │ ├── jquery.gritter.css
-│ │ ├── jquery-ui-1.10.3.custom.min.css
-│ │ └── jquery-ui-1.10.3.full.min.css
-│ └── js
-│ ├── jquery-2.0.3.min.js
-│ ├── jquery.dataTables.bootstrap.js
-│ ├── jquery.dataTables.min.js
-│ ├── jquery.easy-pie-chart.min.js
-│ ├── jquery.gritter.min.js
-│ ├── jquery.hotkeys.min.js
-│ ├── jquery.maskedinput.min.js
-│ ├── jquery.mobile.custom.min.js
-│ ├── jquery.slimscroll.min.js
-│ ├── jquery-ui-1.10.3.custom.min.js
-│ └── jquery-ui-1.10.3.full.min.js
-└── stylesheets
- ├── application.css
- └── bootstrap.min.css
-</code></pre>
-<p>Effectively, asset-pipeline treats each of the subdirectories of <code>grails-app/assets</code> as another root for locating assets.</p>
-<h2>Conclusion</h2>
-<p>As you have seen in this post, it's pretty simple to organize the static resources using asset-pipeline plugin and migrate from resources.</p>
-<p>If you want to take a closer look to the code, this example application is available <a href="https://github.com/ilopmar/example-asset-pipeline">here</a>.</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-6.png)'>
- <a href='https://grails.org/blog/2021-04-07-publish-grails-plugin-to-maven-central.html'>
- <h3>April 7, 2021</h3>
- <h2>How to Publish a Grails Plugin to the Maven C...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-5.png)'>
- <a href='https://grails.org/blog/2021-02-12-alerts-regarding-bintray-sunset.html'>
- <h3>February 12, 2021</h3>
- <h2>Important Information Regarding Grails and Bi...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-09-23.jpg)'>
- <a href='https://grails.org/blog/2018-09-23.html'>
- <h3>September 23, 2018</h3>
- <h2>Security Vulnerability in Asset-Pipeline and ...</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-09-12.html">https://grails.apache.org/blog/2016-09-12.html</a></p>
</body>
</html>
diff --git a/blog/2016-09-28.html b/blog/2016-09-28.html
index c18da6290b..9d48e4ca0a 100644
--- a/blog/2016-09-28.html
+++ b/blog/2016-09-28.html
@@ -1,180 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Grails® 3.2 and GORM 6.0 Released</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="GA releases of Grails 3.2 and GORM 6.0" />
- <meta name="date" content="September 28, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='GA releases of Grails 3.2 and GORM 6.0'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Grails® 3.2 and GORM 6.0 Released'/>
- <meta property='og:description' content='GA releases of Grails 3.2 and GORM 6.0'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-09-28.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Grails® 3.2 and GORM 6.0 Released</h1>
-<p><span class="author">By Graeme Rocher</span></p>
-<p><span class="date">September 28, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/release.html"><span class="hashtag">#release</span></a></p>
-<p>Today we are pleased to announce the GA releases of <a href="https://github.com/grails/grails-core/releases/tag/v3.2.0">Grails<sup>®</sup> 3.2</a> and <a href="https://gorm.grails.org/latest/">GORM 6.0</a>.</p>
-<p>Each of these releases represents a significant step forward for the framework and marks the second major release since <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) began sponsoring development.</p>
-<h2>GORM 6.0</h2>
-<p><a href="https://gorm.grails.org/6.0.x">GORM 6.0</a> continues our goal of making GORM a standalone technology that can be used outside of the Grails framework. By separating GORM from the Spring container, it is now easier to bootstrap and use GORM in a range of different scenarios, from usage in Grails apps to Spring Boot apps to within a unit test.</p>
-<p>In addition we have addressed often-requested features in GORM including:</p>
-<ul>
-<li>Multiple Data Sources Support for MongoDB and Neo4j</li>
-<li>Unified multi-tenancy support for Hibernate, MongoDB and Neo4j</li>
-<li>GORM for MongoDB 3.3 driver</li>
-<li>GORM for Neo4j 3.0 and Bolt Driver support</li>
-<li>Unified configuration across all implementations</li>
-</ul>
-<p>There is so much new and improved functionality in GORM that we prepared a dedicated "<a href="https://gorm.grails.org/latest/whatsNew/manual/index.html">What's New" guide</a> just for GORM 6.0.</p>
-<p>Also, check out the <a href="https://gorm.grails.org/latest/">brand new GORM 6 website</a> for links to documentation for each implementation of GORM.</p>
-<h2>RxGORM</h2>
-<p>In additional to the traditional GORM API, a new API for GORM has been introduced based on <a href="https://github.com/ReactiveX/RxJava/wiki">RxJava</a> called <a href="https://gorm.grails.org/6.0.x/rx/manual/index.html">RxGORM</a>. With RxGORM you can write non-blocking, reactive data access code for supported implements.</p>
-<p>For the first release of RxGORM, implementations for <a href="https://gorm.grails.org/6.0.x/rx/manual/index.html">MongoDB</a> and <a href="https://gorm.grails.org/6.0.x/rx/rest-client/manual/index.html">REST</a> are provided, with more implementations planned.</p>
-<h2>Grails 3.2</h2>
-<p>Grails 3.2 bundles all of the goodness of GORM 6, plus a whole bunch of new features in the core framework:</p>
-<ul>
-<li>RxJava support via a <a href="https://grails.org/plugins.html#plugin/rxjava">new plugin</a>.</li>
-<li>Improved <a href="https://views.grails.org/">JSON View</a> support.</li>
-<li>AngularJS scaffolding</li>
-<li>REST improvements</li>
-<li>Latest and greatest libraries (Spring Boot 1.4, Gradle 3.0, etc.)</li>
-</ul>
-<p>These are just some of the highlights. I recommend checking out the dedicated <a href="https://docs.grails.org/3.2.x/guide/introduction.html#whatsNew">"What's New"</a> section in the brand new Asciidoctor-based <a href="https://docs.grails.org/3.2.x">user guide</a> for more information.</p>
-<p>Finally, thanks to all those who contributed feedback and issue reports to the release. We look forward to the continued participation of the Grails community as the framework continues to evolve.</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2019-07-11.jpg)'>
- <a href='https://grails.org/blog/2019-07-11.html'>
- <h3>July 11, 2019</h3>
- <h2>Grails® 4 GA Released</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2019-02-19.jpg)'>
- <a href='https://grails.org/blog/2019-02-19.html'>
- <h3>February 19, 2019</h3>
- <h2>Grails® 4 Milestone 1 Released</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2017-07-26.jpg)'>
- <a href='https://grails.org/blog/2017-07-26.html'>
- <h3>July 26, 2017</h3>
- <h2>Grails® 3.3 GA Released</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-09-28.html">https://grails.apache.org/blog/2016-09-28.html</a></p>
</body>
</html>
diff --git a/blog/2016-10-03.html b/blog/2016-10-03.html
index 989b613d90..79a464de06 100644
--- a/blog/2016-10-03.html
+++ b/blog/2016-10-03.html
@@ -1,400 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>How to Use Travis-CI to Build and Deploy Your Plugin</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="How to Use Travis-CI to Build and Deploy Your Grails® 3 Plugin" />
- <meta name="date" content="October 3, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='How to Use Travis-CI to Build and Deploy Your Grails® 3 Plugin'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='How to Use Travis-CI to Build and Deploy Your Plugin'/>
- <meta property='og:description' content='How to Use Travis-CI to Build and Deploy Your Grails® 3 Plugin'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-10-03.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>How to Use Travis-CI to Build and Deploy Your Plugin</h1>
-<p><span class="author">By Søren Berg Glasius</span></p>
-<p><span class="date">October 3, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/plugins.html"><span class="hashtag">#plugins</span></a> <a href="https://grails.org/blog/tag/travis.html"><span class="hashtag">#travis</span></a></p>
-<h2>Introduction</h2>
-<p>When you create a Grails<sup>®</sup> 3 plugin and you want to share it with the world, wouldn't it be great if building and deploying was taken care of by a CI server?</p>
-<p>In this blog I will show you how to set up a Grails Plugin project that will be built and deployed on the <a href="https://travis-ci.org/">Travis-CI infrastructure</a>.</p>
-<p>Let us start out by setting up the project, so that it can be deployed to Bintray. Then we will add a Travis build to the mix. Finally we will explore how to handle snapshot deployment to <a href="https://oss.jfrog.org/">JFrog's open source repository</a>.</p>
-<h2>How Travis-CI Works</h2>
-<p>Travis-CI works by monitoring your GitHub repository and whenever it sees changes, it will make a build of your project. The change can be a new commit pushed to GitHub, a new tag pushed to GitHub, or a pull request to your project on GitHub.</p>
-<p>If you want a deeper knowledge on how Travis-CI works, please <a href="https://docs.travis-ci.com/">see the documentation</a>.</p>
-<h2>Getting Started</h2>
-<p>While you might have a plugin already, let us start this example by creating a plugin. The plugin will not have any functionality; it is only here to show the steps.</p>
-<pre><code class="language-bash">grails create-plugin -profile plugin demoplugin
-cd demoplugin
-</code></pre>
-<p>To get Travis-CI working the project has to live on GitHub.</p>
-<h3>Setting Up a GitHub Repository</h3>
-<p>The first step is to enable Git for the local repository, add the project files, and commit it:</p>
-<pre><code class="language-bash">git init
-git add .
-git commit -m "Initial commit"
-</code></pre>
-<p>Now go to <a href="https://github.com/">GitHub</a> where we create a new repository:</p>
-<p><img src="2016-10-03-img01.png" alt="Create a new repository" /></p>
-<p><img src="2016-10-03-img02.png" alt="" /></p>
-<p><img src="2016-10-03-img03.png" alt="" /></p>
-<p>And push the first commit to GitHub:</p>
-<pre><code class="language-bash">git remote add origin https://github.com/sbglasius/demoplugin.git
-git push -u origin master
-</code></pre>
-<h3>Publishing Plugin to Bintray</h3>
-<p>Before configuring Travis, let us update the configuration to enable publishing the plugin to Bintray and the Grails Plugin Portal.</p>
-<p><code>build.gradle</code> already contains the building blocks for this:</p>
-<pre><code class="language-groovy">// ...
-group "org.grails.plugins"
-// ...
-apply plugin:"org.grails.grails-plugin"
-// ...
-grailsPublish {
- // TODO: Provide values here
- user = 'user'
- key = 'key'
- githubSlug = 'foo/bar'
- license {
- name = 'Apache-2.0'
- }
- title = "My Plugin"
- desc = "Full plugin description"
- developers = [johndoe:"John Doe"]
- portalUser = ""
- portalPassword = ""
-}
-</code></pre>
-<p>As can be seen, some values are not filled in, like credentials and <code>githubSlug</code>. Let us add those values in a way where credentials are not visible in the public GitHub repository.</p>
-<p>My code snippet will contain two ways to fetch configuration values:</p>
-<pre><code class="language-groovy">grailsPublish {
- user = System.getenv("BINTRAY_USER") ?: project.bintrayUser
- key = System.getenv("BINTRAY_KEY") ?: project.bintrayKey
- githubSlug = 'https://github.com/sbglasius/demoplugin'
- license {
- name = 'Apache-2.0'
- }
- title = "Demo Plugin"
- desc = "A Demo Plugin, no need to publish"
- developers = [johndoe:"John Doe"]
- portalUser = System.getenv("GRAILS_PORTAL_USER") ?: project.grailsPortalUser
- portalPassword = System.getenv("GRAILS_PORTAL_PASSWORD") ?: project.grailsPortalPassword
-}
-</code></pre>
-<p>The configuration values are now read from either the running environment (this is where Travis will provide them, more on this later) or they will be taken from the project configuration or Gradle's global configuration (<code>~/.gradle/gradle.properties</code>). That is where I recommend storing these credentials.</p>
-<p>The format for <code>~/.gradle/gradle.properties</code> is like this:</p>
-<pre><code class="language-properties">bintrayUser=user
-bintrayKey=[secret]
-
-grailsPortalUser=user
-grailsPortalPassword=[secret]
-</code></pre>
-<p>With this in place, it is now possible to publish the plugin to Bintray. This can be done like this:</p>
-<pre><code class="language-bash">./gradlew bintrayUpload
-</code></pre>
-<p>Before moving on to Travis, let me push this to GitHub:</p>
-<pre><code class="language-bash">git add .
-git commit -m "Build script for Gradle"
-git push
-</code></pre>
-<h2>Set Up Travis Command Line</h2>
-<p>Before we can use Travis, we need to install the Travis Command line. Travis Command line requires Ruby, and since my machine is a Mac, Ruby is included. For other OSes, please go <a href="https://www.ruby-lang.org/en/">here</a> for more information.</p>
-<p>Install Travis</p>
-<pre><code class="language-bash">gem install travis
-</code></pre>
-<h2>Adding Travis to the Project</h2>
-<p>The first thing we will do is initialize Travis for the project.</p>
-<pre><code class="language-bash">$ travis init
-Detected repository as sbglasius/demoplugin, is this correct? |yes|
-Main programming language used: |Ruby| Groovy
-.travis.yml file created!
-sbglasius/demoplugin: enabled :)
-</code></pre>
-<p>Take a look in <code>.travis.yml</code>. You should see one line of code:</p>
-<pre><code class="language-yml">language: groovy
-</code></pre>
-<p>Let us push this change to GitHub:</p>
-<pre><code class="language-bash">git add .travis.yml
-git commit -m "Added travis config"
-git push
-</code></pre>
-<p>This will result in the first Travis build – a failed build. When Travis tries to run <code>gradle assemble</code> it fails with the following error:</p>
-<pre><code class="language-text">FAILURE: Build failed with an exception.
-* Where:
-Build file '/home/travis/build/sbglasius/demoplugin/build.gradle' line: 50
-* What went wrong:
-A problem occurred evaluating root project 'demoplugin'.
-> Could not find property 'bintrayUser' on root project 'demoplugin'.
-* Try:
-Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
-BUILD FAILED
-</code></pre>
-<p>As we can see from the error, it cannot find the <code>bintrayUser</code> in the properties – since it is not defined yet together with the other credential properties.</p>
-<p>Travis has the ability to set environment variables defined in .travis.yml, but we do not want credentials in clear text. Fortunately, Travis support <a href="https://docs.travis-ci.com/user/environment-variables#Defining-Variables-in-.travis.yml">encrypting environment variables</a>. It is important to understand that the variables added here will only work for the GitHub account associated with the project.</p>
-<h3>Adding Environment Variables to <code>.travis.yml.</code></h3>
-<p>Let us add four variables to the configuration under <code>env.global</code>:</p>
-<pre><code class="language-bash">travis encrypt BINTRAY_USER=user --add env.global
-travis encrypt BINTRAY_KEY=*** --add env.global
-travis encrypt GRAILS_PORTAL_USER=user --add env.global
-travis encrypt GRAILS_PORTAL_PASSWORD=[secret] --add env.global
-</code></pre>
-<p>Now <code>.travis.yml</code> looks like this:</p>
-<pre><code class="language-yml"> language: groovy
-env:
- global:
- - secure: iU4Y3JVWFteYl6J9MIlKv4H6nT0...
- - secure: xPW7KBPVHe64hMloY30Oa5WowYO...
- - secure: mhCnvHfjPX+wudLOfo6B8MFVGBV...
- - secure: QF0+kEZLjL3ZJe0U/5jKC1dijgm...
-</code></pre>
-<p>and then commit and push to GitHub.</p>
-<p><em>Now the build goes green on Travis</em>, but it is still not publishing the plugin to Bintray. That's up next.</p>
-<h2>Publish to Bintray with Travis</h2>
-<p>Travis should test <code>master</code> on GitHub every time code is committed. It should build pull-requests but should only release the plugin to Bintray, when Git is tagged with a new version.</p>
-<p>The developers of Travis have thought of this and allow us to use a bash script to make more fine-grained logic. The basic script could look like this:</p>
-<pre><code class="language-bash">#!/usr/bin/env bash
-
-set -e
-./gradlew clean check assemble --stacktrace
-
-EXIT_STATUS=0
-echo "Publishing archives for branch $TRAVIS_BRANCH"
-if [[ -n $TRAVIS_TAG ]] || [[ $TRAVIS_BRANCH == 'master' && $TRAVIS_PULL_REQUEST == 'false' ]]; then
- if [[ -n $TRAVIS_TAG ]]; then
- echo "Pushing build to Bintray"
- ./gradlew bintrayUpload notifyPluginPortal || EXIT_STATUS=$?
- fi
-fi
-exit $EXIT_STATUS
-fi
-</code></pre>
-<p>The script is currently a bit more advanced than it needs to be; that is because more functionality will be added later.</p>
-<p>To execute the script on Travis-CI add these few lines to <code>.travis.yml</code>:</p>
-<pre><code class="language-yml">before_script:
-- rm -rf target
-script: ./travis-build.sh
-</code></pre>
-<p>I prefer them before the <code>env:</code> block. To allow Travis to actually execute the script, it's important that the script execute flag on <code>travis-build.sh</code> is set:</p>
-<pre><code class="language-bash">chmod 755 travis-build.sh
-</code></pre>
-<p>Add, commit, and push this to GitHub like before.</p>
-<p>The result will be a successful build, but not a deployment to Bintray. This is of course due to the <code>if</code> statement in the bash script, which checks if a git tag is set. If it is the <code>master</code> branch and if it's not a pull-request.</p>
-<h3>Tag and Release</h3>
-<p>I now want to make a release of my plugin. To do so, I need to bump the plugin version in <code>build.gradle</code>, commit the change, tag the commit, and push it to GitHub.</p>
-<p>Let me start with <code>build.gradle</code></p>
-<pre><code class="language-groovy">version "0.2"
-</code></pre>
-<p>and the commit, tag, and push:</p>
-<pre><code class="language-bash">git commit -a -m "Bump revision to 0.2"
-git tag "0.2"
-git push --tags
-</code></pre>
-<p>Notice, that I added <code>--tags</code> to the <code>git</code> command to get tags pushed to GitHub.</p>
-<p>That's it. The build is automated, and a release can be created on Bintray by using Travis-CI and GitHub tagging.</p>
-<h2>Deploy Snapshots to JFrog OSS Artifactory</h2>
-<p>To have snapshot published to a public repo for others to use it, we can resort to Jfrog OSS Artifactory <a href="https://oss.jfrog.org/">oss.jfrog.org (OJO)</a>, since Bintray does not support snapshot builds. (This section is inspired by the <a href="https://www.slideshare.net/alvarosanchezmariscal/mastering-grails-3-plugins-greach-2016">blog post by Álvaro Sánchez</a>). Before you can publish to OJO, please read <a href="https://www.jfrog.com/confluence/display/RTF/Deploying+Snapsh [...]
-<h3>Setup Build Scripts</h3>
-<p>Let us start with <code>build.gradle</code>:</p>
-<pre><code class="language-groovy">buildscript {
- //...
-}
-plugins {
- id "com.jfrog.artifactory" version "4.4.0"
-}
-
-version "0.3-SNAPSHOT"
-group "demoplugin"
-//...
-grailsPublish {
- //...
-}
-artifactory {
- contextUrl = 'https://oss.jfrog.org'
- publish {
- repository {
- repoKey = 'oss-snapshot-local'
- username = System.getenv("BINTRAY_USER") ?: project.bintrayUser
- password = System.getenv("BINTRAY_KEY") ?: project.bintrayKey
- }
- defaults {
- publications('maven')
- }
- }
-}
-</code></pre>
-<p>Since OJO and Bintray are tightly coupled, it is the same credentials used.</p>
-<p>Updated <code>travis-build.sh</code></p>
-<pre><code class="language-bash">#!/usr/bin/env bash
-
-set -e
-./gradlew clean check assemble --stacktrace
-
-EXIT_STATUS=0
-echo "Publishing archives for branch $TRAVIS_BRANCH"
-if [[ -n $TRAVIS_TAG ]] || [[ $TRAVIS_BRANCH == 'master' && $TRAVIS_PULL_REQUEST == 'false' ]]; then
- if [[ -n $TRAVIS_TAG ]]; then
- echo "Pushing build to Bintray"
- ./gradlew bintrayUpload || EXIT_STATUS=$?
- else
- echo "Publishing snapshot to OJO"
- ./gradlew artifactoryPublish || EXIT_STATUS=$?
- fi
-fi
-exit $EXIT_STATUS
-fi
-</code></pre>
-<p>Commit and push to GitHub and go watch the build on Travis-CI. Notice, that the build ends with a push to OJO.</p>
-<p>That's it. Travis-CI will now publish both snapshot versions and tagged versions to OJO and Bintray.</p>
-<p>But wait – there is a bit more.</p>
-<h2>Optimizing Travis-CI setup</h2>
-<p>Take a look at the log-output from Travis-CI and notice that it downloads Gradle and all of the maven dependencies on each build.</p>
-<p>Travis-CI supports caching of these artifacts and a couple of other options.</p>
-<p>Add the following to <code>.travis.yml</code> just below the <code>language: groovy</code> block:</p>
-<pre><code class="language-yml">sudo: false # run on container-based infrastructure
-
-before_cache:
- - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
-cache:
- directories:
- - $HOME/.gradle/caches/
- - $HOME/.gradle/wrapper/
- - $HOME/.m2/repositories/
-</code></pre>
-<p>This will reduce downloads and build time on Travis-CI.</p>
-<h2>Conclusion</h2>
-<p>Travis-CI is a great tool to build and deploy your Grails plugin; it will help you maintain your code when receiving pull requests from the community. Happy CI'ing!</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-6.png)'>
- <a href='https://grails.org/blog/2021-04-07-publish-grails-plugin-to-maven-central.html'>
- <h3>April 7, 2021</h3>
- <h2>How to Publish a Grails Plugin to the Maven C...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-5.png)'>
- <a href='https://grails.org/blog/2021-02-12-alerts-regarding-bintray-sunset.html'>
- <h3>February 12, 2021</h3>
- <h2>Important Information Regarding Grails and Bi...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-09-23.jpg)'>
- <a href='https://grails.org/blog/2018-09-23.html'>
- <h3>September 23, 2018</h3>
- <h2>Security Vulnerability in Asset-Pipeline and ...</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-10-03.html">https://grails.apache.org/blog/2016-10-03.html</a></p>
</body>
</html>
diff --git a/blog/2016-11-01.html b/blog/2016-11-01.html
index 689bda2503..b92295b07d 100644
--- a/blog/2016-11-01.html
+++ b/blog/2016-11-01.html
@@ -1,281 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Configuring Rolling Logging with Logback</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Learn how to configure rolling log system in Grails® apps, so that log files are rolled over on a schedule and archived after a certain point." />
- <meta name="date" content="November 1, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Learn how to configure rolling log system in Grails® apps, so that log files are rolled over on a schedule and archived after a certain point.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Configuring Rolling Logging with Logback'/>
- <meta property='og:description' content='Learn how to configure rolling log system in Grails® apps, so that log files are rolled over on a schedule and archived after a certain point.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-11-01.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Configuring Rolling Logging with Logback</h1>
-<p><span class="author">By Zachary Klein</span></p>
-<p><span class="date">November 1, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/logging.html"><span class="hashtag">#logging</span></a> <a href="https://grails.org/blog/tag/logback.html"><span class="hashtag">#logback</span></a> <a href="https://grails.org/blog/tag/config.html"><span class="hashtag">#config</span></a></p>
-<p>A common requirement in web applications is to support a rolling log system, so that log files are rolled over on a schedule and archived after a certain point. Grails<sup>®</sup> 3 uses Logback (considered the successor to log4j) as its logging library, and it's quite simple to configure a rolling appender using Logback's Groovy config format.</p>
-<p>The Grails framework includes a default Logback configuration at <code>grails-app/conf/logback.groovy</code>. By default (as of Grails 3.2.1), this file (which follows the standard Logback groovy config format) configures a single appender, an instance of <code>ConsoleAppender</code> called <code>STDOUT</code>, and conditionally (when in development mode) an instance of <code>FileAppender</code> called <code>FULL_STACKTRACE</code>. These may then be used by logger instances, which can [...]
-<p>The default <code>logback.groovy</code> file in Grails 3.2.1 is shown below.</p>
-<pre><code class="language-groovy">//grails-app/confg/logback.groovy
-import grails.util.BuildSettings
-import grails.util.Environment
-
-// See https://logback.qos.ch/manual/groovy.html for details on configuration
-appender('STDOUT', ConsoleAppender) {
- encoder(PatternLayoutEncoder) {
- pattern = "%level %logger - %msg%n"
- }
-}
-
-def targetDir = BuildSettings.TARGET_DIR
-if (Environment.isDevelopmentMode() && targetDir != null) {
- appender("FULL_STACKTRACE", FileAppender) {
- file = "${targetDir}/stacktrace.log"
- append = true
- encoder(PatternLayoutEncoder) {
- pattern = "%level %logger - %msg%n"
- }
- }
- logger("StackTrace", ERROR, ['FULL_STACKTRACE'], false)
- root(ERROR, ['STDOUT', 'FULL_STACKTRACE'])
-}
-else {
- root(ERROR, ['STDOUT'])
-}
-</code></pre>
-<p>Let's add an instance of <a href="https://logback.qos.ch/manual/appenders.html#RollingFileAppender"><code>RollingFileAppender</code></a> for our production environment. Let's say we want to split out our log files by day, and keep 30 days worth of log files around (deleting any older ones). In addition, we don't have unlimited hard drive space, so we'll also set a file size cap so that the total disk space used by our logs never exceeds 2GB.</p>
-<p>Here's our new appender:</p>
-<pre><code class="language-groovy">//grails-app/confg/logback.groovy
-import ch.qos.logback.core.rolling.RollingFileAppender
-import ch.qos.logback.core.rolling.TimeBasedRollingPolicy
-import ch.qos.logback.core.util.FileSize
-
-
-def HOME_DIR = "."
-
-appender("ROLLING", RollingFileAppender) {
- encoder(PatternLayoutEncoder) {
- pattern = "%level %logger - %msg%n"
- }
- rollingPolicy(TimeBasedRollingPolicy) {
- fileNamePattern = "${HOME_DIR}/logs/myApp-%d{yyyy-MM-dd_HH-mm}.log"
- maxHistory = 30
- totalSizeCap = FileSize.valueOf("2GB")
- }
-}
-</code></pre>
-<p>An instance of <code>RollingFileAppender</code> needs two "policies", a <code>rollingPolicy</code> (to define how to perform the rollover), and a <code>triggerPolicy</code> (which specifies when the rollover should occur). In this case, our <code>rollingPolicy</code> is <code>TimeBasedRollingPolicy</code>, which happens to implement the <code>TriggeringPolicy</code> interface and therefore satisfies both policy requirements. <code>TimeBasedRollingPolicy</code> is one of the [...]
-<p><code>TimeBasedRollingPolicy</code> gets both it's rolling behavior (creating a new log file with the current date/time in the file name) and it's triggering behavior (rollover will occur based on the specified timestamp pattern) from the <code>fileNamePattern</code> property.</p>
-<blockquote>
-<h2>What's In a Name?</h2>
-<p>Maybe you'd rather not have the filenames of your log files contain the trigger interval. No worries, <code>RollingFileAppender</code> also supports a <code>file</code> property which can override this behavior, so your log files can be rolled over monthly (for example) without actually containing the date string in their filenames. See the documentation for <a href="https://logback.qos.ch/manual/appenders.html#RollingFileAppender"><code>RollingFileAppender</code></a> for more details.</p>
-</blockquote>
-<p>The trigger policy is the most interesting part here - it takes an approach that bases the rollover occurrence on how specific you define the timestamp in the <code>fileNamePattern</code>. So if you specify down to the month, rollover will occur each month. Specify a pattern down to the day, and it will occur daily). It's easier to understand when you see it in action, so here's some example patterns taken from Logback's documentation:</p>
-<pre><code class="language-groovy"> fileNamePattern = "/myApp-log.%d{yyyy-MM}.log" //Rollover at the beginning of each month, file format: myApp-log.2016-11.log
- fileNamePattern = "/myApp-log.%d{yyyy-ww}.log" //Rollover at the first day of each week. Note that the first day of the week depends on the locale.
- fileNamePattern = "/myApp-log.%d{yyyy-MM-dd_HH}.log" //Rollover at the top of each hour.
-</code></pre>
-<p>Note that in the above examples we are configuring the timestamp in the filename of the log files. We can also use the timestamp to create a file directory structure, like this example:</p>
-<pre><code class="language-groovy">fileNamePattern = "/logs/%d{yyyy/MM}/myApp.log" //Rollover at the beginning of each month.
-//Each log file will be stored in a year/month directory, e.g: /logs/2016/11/myApp.log, /logs/2016/12/myApp.log, /logs/2017/01/myApp.log
-</code></pre>
-<p>Finally, adding a <code>zip</code> or <code>gz</code> file extension to our <code>fileNamePattern</code> will apply the selected compression to the rolled-over log files:</p>
-<pre><code class="language-groovy">fileNamePattern = "/myApp-log.%d{yyyy/MM}.gz" //Rollover at the beginning of each month, compress the rolled-over file with GZIP
-</code></pre>
-<p>Going back to our previous example, we're setting a couple more properties on our <code>TimeBasedRollingPolicy</code> - <code>maxHistory</code> and <code>totalSizeCap</code>. These are pretty simple to understand; <code>maxHistory</code> sets the upper limit on how many log files to preserve (when the max is reached the oldest file is deleted), and <code>totalSizeCap</code> sets a cap on how much disk space our log files are allowed to use (again, when the cap is reached the oldest f [...]
-<blockquote>
-<h2>Warning!</h2>
-</blockquote>
-<blockquote>
-<p>While the Logback docs suggest that <code>totalSizeCap</code> can be specified as a plain String (i.e, "2GB"), I've found that it needs to be specified as a <code>FileSize</code> to avoid casting exceptions - so make sure to use <code>FileSize.valueOf("2GB")</code> to evaluate your total size. This also applies to the <code>maxFileSize</code> property used in the <code>SizeBasedRollingPolicy</code> and <code>TimeAndSizeBasedRollingPolicy</code>.</p>
-</blockquote>
-<p>There are several more <a href="https://logback.qos.ch/manual/appenders.html#onRollingPolicies">rolling & triggering policies</a> that are available, including <a href="https://logback.qos.ch/manual/appenders.html#SizeBasedTriggeringPolicy"><code>SizeBasedTriggerPolicy</code></a> and <a href="https://logback.qos.ch/manual/appenders.html#SizeAndTimeBasedRollingPolicy"><code>SizeAndTimeBasedTriggeringPolicy</code></a>, and <code>FixedWindowRollingPolicy</code></p>
-<p>Finally, let's specify that we want our new <code>RollingFileAppender</code> to be used in production mode only, while keeping the default <code>ConsoleAppender</code> for development mode.</p>
-<pre><code class="language-groovy">//grails-app/confg/logback.groovy
-import grails.util.BuildSettings
-import grails.util.Environment
-import ch.qos.logback.core.rolling.RollingFileAppender
-import ch.qos.logback.core.rolling.TimeBasedRollingPolicy
-import ch.qos.logback.core.util.FileSize
-
-def HOME_DIR = "."
-
-// See https://logback.qos.ch/manual/groovy.html for details on configuration
-appender('STDOUT', ConsoleAppender) {
- encoder(PatternLayoutEncoder) {
- pattern = "%level %logger - %msg%n"
- }
-}
-
-appender("ROLLING", RollingFileAppender) {
- encoder(PatternLayoutEncoder) {
- pattern = "%level %logger - %msg%n"
- }
- rollingPolicy(TimeBasedRollingPolicy) {
- fileNamePattern = "${HOME_DIR}/logs/myApp-%d{yyyy-MM-dd_HH-mm}.log"
- maxHistory = 30
- totalSizeCap = FileSize.valueOf("2GB")
- }
-}
-
-def targetDir = BuildSettings.TARGET_DIR
-if (Environment.isDevelopmentMode() && targetDir != null) {
- appender("FULL_STACKTRACE", FileAppender) {
- file = "${targetDir}/stacktrace.log"
- append = true
- encoder(PatternLayoutEncoder) {
- pattern = "%level %logger - %msg%n"
- }
- }
-
- logger("StackTrace", ERROR, ['FULL_STACKTRACE'], false)
- root(ERROR, ['STDOUT', 'FULL_STACKTRACE'])
-}
-else {
- root(ERROR, ['ROLLING'])
-}
-</code></pre>
-<p>And with that, we have our rolling log system. Enjoy!</p>
-<h2>Resources</h2>
-<ul>
-<li>Logback documentions: <a href="https://logback.qos.ch/documentation.html">https://logback.qos.ch/documentation.html</a></li>
-<li>Logback Groovy config (from the official docs): <a href="https://logback.qos.ch/manual/groovy.html">https://logback.qos.ch/manual/groovy.html</a></li>
-<li>DZone - Logback Configuration Using Groovy: <a href="https://dzone.com/articles/logback-configuration-using-groovy">https://dzone.com/articles/logback-configuration-using-groovy</a></li>
-</ul>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-03-introducing-grails-6-2-3.html'>
- <h3>January 3, 2025</h3>
- <h2>Introducing Grails Framework 6.2.3 Release</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-02-grails-community-rockstar-fredley.html'>
- <h3>January 2, 2025</h3>
- <h2>James Fredley Named 2025 Grails® Rock Star</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-11-01.html">https://grails.apache.org/blog/2016-11-01.html</a></p>
</body>
</html>
diff --git a/blog/2016-11-10.html b/blog/2016-11-10.html
index 17243d3469..d31a13b5d5 100644
--- a/blog/2016-11-10.html
+++ b/blog/2016-11-10.html
@@ -1,239 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Deploying Grails® 3.2 to JBoss 7.1 EAP</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Learn the steps involved to deploy a Grails 3 app to JBoss 7.1 EAP" />
- <meta name="date" content="November 10, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Learn the steps involved to deploy a Grails 3 app to JBoss 7.1 EAP'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Deploying Grails® 3.2 to JBoss 7.1 EAP'/>
- <meta property='og:description' content='Learn the steps involved to deploy a Grails 3 app to JBoss 7.1 EAP'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-11-10.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Deploying Grails® 3.2 to JBoss 7.1 EAP</h1>
-<p><span class="author">By Graeme Rocher</span></p>
-<p><span class="date">November 10, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/deployment.html"><span class="hashtag">#deployment</span></a></p>
-<p>Following on from our post describing <a href="">how to deploy Grails<sup>®</sup> 3 to JBoss 6.4 EAP</a>, I recently undertook a new adventure to deploy Grails 3.2.3 to <a href="https://www.jboss.org/">JBoss 7.1 EAP</a>.</p>
-<p>Like every new version of JBoss there are dependency challenges and tweaks to overcome in order to get to the point where you can deploy an application.</p>
-<h2>Configuring Gradle</h2>
-<p>After you have created a Grails application using the <code>grails create-app</code> command the first thing that needs to be done is to modify the dependencies to versions compatible with JBoss 7.1.</p>
-<p>JBoss 7.1 is based on Servlet 3.0 and earlier versions of the Bean Validation API. This means that you need to use Tomcat 7, which is based on Servlet 3.0, which you can do by specifying the Tomcat version in <code>build.gradle</code>:</p>
-<pre><code class="language-groovy">ext['tomcat.version'] = '7.0.72'
-</code></pre>
-<p>The above uses Spring Boot's ability to override the default versions of the <code>org.springframework.boot:spring-boot-starter-tomcat</code> dependency. Speaking of the <code>spring-boot-starter-tomcat</code> dependency, you need to make it provided:</p>
-<pre><code class="language-groovy">provided "org.springframework.boot:spring-boot-starter-tomcat"
-</code></pre>
-<p>Since the classes within the Tomcat JARs are already provided by Tomcat these should not be included in the WAR. Next you should also specify the Servlet 3.0 API as provided:</p>
-<pre><code class="language-groovy">provided "javax.servlet:javax.servlet-api:3.0.1"
-</code></pre>
-<p>This does two things, firstly it ensures the Servlet API dependencies are not in the WAR and secondly it forces the Grails framework to use Servlet 3.0 instead of the default 3.1.</p>
-<p>The next challenge is the Bean Validation API, in earlier versions of JBoss it was possible to exclude the validation module and ship with a custom version of the Bean Validation API, this no longer seems to be possible with JBoss 7 so you have to downgrade the version of Hibernate Validator used by the Grails framework:</p>
-<pre><code class="language-groovy">compile "org.hibernate:hibernate-validator:4.3.2.Final"
-</code></pre>
-<p>The JAXB dependency also seems be a required dependency of JBoss 7 so you have to add that:</p>
-<pre><code class="language-groovy">runtime 'javax.xml.bind:jaxb-api:2.2.12'
-</code></pre>
-<p>Finally, generally with JBoss 7 you should deploy with a JNDI datasource so you should make the database driver dependency you are using <code>provided</code> scope. For example for MySQL:</p>
-<pre><code class="language-groovy">provided "mysql:mysql-connector-java"
-</code></pre>
-<h2>JBoss Deployment Descriptors</h2>
-<p>The next step to getting JBoss configured correctly is to provide a <code>src/main/webapp/WEB-INF/jboss-deployment-structure.xml</code> file, the contents of which should look like the following:</p>
-<pre><code class="language-xml"><?xml version='1.0' encoding='UTF-8'?>
-<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">
- <deployment>
- <exclusions>
- <module name="org.jboss.logging" />
- <module name="org.hibernate" />
- <module name="org.hibernate.validator" />
- </exclusions>
- </deployment>
-</jboss-deployment-structure>
-</code></pre>
-<p>The reason for this is to isolate and exclude dependencies you don't want to inherit from JBoss 7. I also recommend disabling Spring Boot re-packaging of the WAR file if you don't plan to run as a standalone WAR. You can do that by adding the following to <code>build.gradle</code>:</p>
-<pre><code class="language-groovy">bootRepackage.enabled = false
-</code></pre>
-<h2>JNDI DataSource Configuration</h2>
-<p>To configure a JNDI datasource you should first define the production data source as using JNDI:</p>
-<pre><code class="language-yaml">environments:
- development:
- dataSource:
- dbCreate: create-drop
- url: jdbc:h2:mem:devDb
- test:
- dataSource:
- dbCreate: update
- url: jdbc:h2:mem:testDb
- production:
- dataSource:
- jndiName: "java:jboss/datasources/MyDataSource"
- dbCreate: none
-</code></pre>
-<p>Note that you typically do not want the Grails tooling to create the schema for you so we set <code>dbCreate</code> to <code>none</code>. You can then run <code>grails schema-export</code> to generate a <code>build/ddl.sql</code> file that you can use to create the database in your production environment.</p>
-<p>On the JBoss side if you are using standalone deployment, you need to modify the <code>standalone/configuration/standalone.xml</code> file to configure your JNDI datasource. For example for MySQL adding the following section within the <code><datasources></code> block will do:</p>
-<pre><code class="language-xml"> <datasource jndi-name="java:jboss/datasources/MyDataSource" pool-name="MyDataSource">
- <connection-url>jdbc:mysql://localhost:3306/my-database</connection-url>
- <driver>com.mysql</driver>
- <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
- <pool>
- <min-pool-size>10</min-pool-size>
- <max-pool-size>100</max-pool-size>
- <prefill>true</prefill>
- </pool>
- <security>
- <user-name>root</user-name>
- </security>
- <statement>
- <prepared-statement-cache-size>32</prepared-statement-cache-size>
- <share-prepared-statements>true</share-prepared-statements>
- </statement>
- </datasource>
-</code></pre>
-<h2>Deploying the Application</h2>
-<p>Once you have prepared your application for deployment to deploy the app you can run <code>gradle assemble</code> to build a WAR file and then copy the generated WAR file located in <code>build/libs</code> to JBoss 7's <code>standalone/deployments</code> directory and then run <code>bin/standalone.sh</code>.</p>
-<p>Note that if you receive an exception that looks like the following:</p>
-<pre><code class="language-groovy">16:45:35,789 WARN [org.jboss.as.ee] (MSC service thread 1-6) JBAS011006: Not installing optional component org.springframework.web.context.request.async.StandardServletAsyncWebRequest due to exception: org.jboss.as.server.deployment.DeploymentUnitProcessingException: JBAS011054: Could not find default constructor for class org.springframework.web.context.request.async.StandardServletAsyncWebRequest
- at org.jboss.as.ee.component.ComponentDescription$DefaultComponentConfigurator.configure(ComponentDescription.java:606)
-</code></pre>
-<p>This is apparently <a href="https://stackoverflow.com/questions/13786685/spring3-2-and-jboss-as-7">normal behaviour</a> and can be safely ignored.</p>
-<h2>This Is WAY Too Hard</h2>
-<p>I agree. Deploying to "enterprise" containers is not fun. It can, however, be a requirement where you work. In order to simplify these steps I have created a JBoss 7 profile for Grails apps that tries to encapsulate all these changes. Simply run:</p>
-<pre><code class="language-bah">grails create-app myapp --profile org.grails.profiles:web-jboss7:1.0.0.RC1
-</code></pre>
-<p>This will create an application in the <code>myapp</code> directory with all the changes necessary apart from preparing the JNDI datasource. Hopefully the profile encourages more JBoss 7 folks to give the Grails framework a try. Happy deploying!</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2019-01-07.jpg)'>
- <a href='https://grails.org/blog/2019-01-07.html'>
- <h3>January 7, 2019</h3>
- <h2>SDKMAN! with Travis</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2017-06-28.jpg)'>
- <a href='https://grails.org/blog/2017-06-28.html'>
- <h3>June 28, 2017</h3>
- <h2>Running a Grails® 3 App With a Self-Signed SS...</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-11-10.html">https://grails.apache.org/blog/2016-11-10.html</a></p>
</body>
</html>
diff --git a/blog/2016-11-14.html b/blog/2016-11-14.html
index 7389114999..3040573a34 100644
--- a/blog/2016-11-14.html
+++ b/blog/2016-11-14.html
@@ -1,223 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Introducing the React Profile for Grails®</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Learn about Grails® React profiles, one aimed at monolithic Grails applications, and a second profile which generates a multi-project client/server structure." />
- <meta name="date" content="November 14, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Learn about Grails® React profiles, one aimed at monolithic Grails applications, and a second profile which generates a multi-project client/server structure.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Introducing the React Profile for Grails®'/>
- <meta property='og:description' content='Learn about Grails® React profiles, one aimed at monolithic Grails applications, and a second profile which generates a multi-project client/server structure.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-11-14.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Introducing the React Profile for Grails®</h1>
-<p><span class="author">By Zachary Klein</span></p>
-<p><span class="date">November 14, 2016</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/react.html"><span class="hashtag">#react</span></a></p>
-<h2>React Profiles for the Grails<sup>®</sup> framework</h2>
-<p>Grails 3 offers great support for the Angular framework, including the Angular Scaffolding plugin as well as profiles for both Angular 1.x and 2.x. Recently new profiles have been released to provide support for creating React applications with Grails 3.</p>
-<p>This post will cover <em>two new profiles for React</em>, one aimed at monolithic Grails applications, and a second profile which makes use of the brand new <a href="https://github.com/facebookincubator/create-react-app"><code>create-react-app</code> CLI</a> and generates a multi-project client/server structure.</p>
-<p><img src="2016-11-14-img01.png" alt="" /></p>
-<h2>React & Webpack Profiles</h2>
-<p>If you've read the previous post on <a href="https://grails.org/blog/2016-05-28.html">Using React with the Grails framework</a>, you've probably noticed that there's quite a bit of wiring that has to happen to get React working properly in the context of a Grails application. This is a place where profiles shine, and now you can get an entire React/Grails project setup immediately upon app generation, including some basic sample React code.</p>
-<pre><code>grails create-app myReactApp --profile=org.grails.profiles:react:1.0.2
-</code></pre>
-<p>The <code>react:1.x</code> profile is based on another new profile, <code>org.grails.profiles:webpack:1.x</code>. The <code>webpack</code> profile can be used standalone as well, if you want to use webpack with another JavaScript framework in a Grails project. In addition, the <code>webpack</code> profile offers a single feature which will configure the <code>babel</code> transpiler with support for ES6 - it also includes sample code to demonstrate the feature.</p>
-<pre><code>grails create-app myWebpackApp --profile=org.grails.profiles:webpack:1.0.2 --features=babel
-</code></pre>
-<p>Both the <code>webpack</code> and <code>react:1.x</code> profiles will expect the JavaScript source files to be kept under <code>/src/main/webapp</code>. You can simply start up your app, and webpack will run automatically and bundle the JavaScript into the Grails asset pipeline. Custom Gradle tasks such as <code>bundle</code> (to generate the webpack bundle on app startup) and <code>webpack</code> (to run webpack in "watch" mode and reload any changes) are defined. You may [...]
-<p>For instance, you can run webpack alongside your Grails app with this command:</p>
-<pre><code>./gradlew webpack //or: npm run webpack
-</code></pre>
-<p>Now when you make changes to your JavaScript/React code under <code>/src/main/webapp</code>, webpack will automatically regenerate the bundle. Just refresh your page to see the changes.</p>
-<p>In addition, the <code>react</code> profile adds a <code>mochaTest</code> task which will run React tests with the mocha test runner. Test sources are kept under <code>/src/test/js</code>, and a simple test is provided. Simply run:</p>
-<pre><code>./gradlew mochaTest //or: npm test
-</code></pre>
-<h2>React Profile - Multi-Project Edition</h2>
-<p>The react profile is being released with two branches, currently <code>1.0.2</code> and <code>2.0.1</code>.</p>
-<p>The <code>react:2.0.1</code> profile is complete rewrite of the 1.x version, and it leverages the new React CLI from Facebook, <code>create-react-app</code>. For more information on the features provided by <code>create-react-app</code>, please read the <a href="https://github.com/facebookincubator/create-react-app">documentation on Github</a>.</p>
-<p>In short, <code>create-react-app</code> provides us with a complete webpack/React project, with custom scripts defined to build, run and test our React app. It is designed for standalone React apps, which makes it a perfect choice for a client/frontend application backed by a separate server application. That is exactly what <code>react:2.0.1</code> provides.</p>
-<p><img src="2016-11-14-img02.png" alt="" /></p>
-<p>Please note that <code>react:2.0.1</code> depends upon the new CORS support in Grails 3.2.1, so you will need to be using that version of Grails or newer.</p>
-<p>To get started with this profile, specify it when generating your app:</p>
-<pre><code>grails create-app myReactMultiApp --profile=org.grails.profiles:react:2.0.1
-</code></pre>
-<p>Take a look at the directory structure - you will see a typical Gradle multi-project build, with separate client and server projects.</p>
-<pre><code>-rw-r--r-- 1 zak staff 65 Nov 1 13:10 build.gradle
-drwxr-xr-x 9 zak staff 306 Nov 1 13:15 client
-drwxr-xr-x 3 zak staff 102 Nov 1 13:10 gradle
--rwxr--r-- 1 zak staff 4971 Nov 1 13:10 gradlew
--rwxr--r-- 1 zak staff 2314 Nov 1 13:10 gradlew.bat
-drwxr-xr-x 8 zak staff 272 Nov 1 13:12 server
--rw-r--r-- 1 zak staff 26 Nov 1 13:10 settings.gradle
-</code></pre>
-<p><code>server</code> is of course our Grails application. The profile will generate a Grails app using the <code>rest-api</code> profile, which provides support for creating domain classes as restful resources as well as JSON and Markup views.</p>
-<p><code>client</code> is our React app. It has been rewritten with React-Bootstrap (Bootstrap 3) and will connect with <code>server</code> via REST calls - it has no Grails dependencies of any kind.</p>
-<pre><code>-rw-r--r-- 1 zak staff 44412 Nov 1 13:10 README.md
--rw-r--r-- 1 zak staff 669 Nov 1 13:10 build.gradle
--rw-r--r-- 1 zak staff 404 Nov 1 13:10 package.json
-drwxr-xr-x 4 zak staff 136 Nov 1 13:10 public
-drwxr-xr-x 10 zak staff 340 Nov 1 13:10 src
-</code></pre>
-<p>This project structure (with the exception of <code>build.gradle</code>, which is specific to the <code>react:2.0.1</code> profile) is all courtesy of <code>create-react-app</code>, and includes an excellent <code>README</code> file. In short, the <code>src/</code> directory is where the React code is kept, <code>public/</code> is for public resources that you wish to make available from your React app without going through webpack's bundling - this directory also includes a template [...]
-<p>One significant customization of the <code>client</code> project (besides the Grails-branded UI) is the file <code>src/config.js</code>. This file is used to specify the URL of the backend, by default <code>http://localhost:8080</code>. It also obtains the current version of the React app from 'package.json'.</p>
-<p>As with the 1.x version of the <code>react</code> profile, this profile define custom Gradle tasks, including a <code>bootRun</code> task to startup the client app. You can either start up the <code>server</code> and <code>client</code> apps separately:</p>
-<pre><code>./gradlew server:bootRun
-
-//in another terminal
-./gradlew client:bootRun
-</code></pre>
-<p>Or you can take advantage of Gradle's parallel execution to run both client and server apps in a single command:</p>
-<pre><code>./gradlew bootRun -parallel
-</code></pre>
-<p>Other tasks defined in <code>client</code> wrap the <code>create-react-app</code> scripts for building and testing the React app. You can run them with the Gradle wrapper, or run the npm scripts directly if you have npm installed.</p>
-<pre><code>./gradlew client:test //or, from the client project dir: npm test
-
-./gradlew client:build //or, from the client project dir: npm run build
-</code></pre>
-<p>Again, please see the <code>create-react-app</code> documentation for more information on leveraging these scripts and the other features provided by <code>create-react-app</code>.</p>
-<h2>Wrap-Up</h2>
-<p>These two profiles offer two ways to use React in the context of a Grails application. If you want to use React within your existing Grails application, either to render components on a GSP or to replace some or all of your GSP pages, then use <code>react:1.0.1</code> (or the latest version of the 1.x branch).</p>
-<p>If you prefer a completely separate frontend for your Grails application, and/or want to take advantage of the features of the <code>create-react-app</code> CLI, then the <code>react:2.0.1</code> (or latest version of the 2.x branch) is made for you.</p>
-<p>Whichever one you choose, here's hoping these profiles help you enjoy using React with Grails 3!</p>
-<h2>Links</h2>
-<ul>
-<li><code>create-react-app</code>: <a href="https://github.com/facebookincubator/create-react-app">https://github.com/facebookincubator/create-react-app</a></li>
-<li>"Using React with the Grails framework": <a href="https://grails.org/blog/2016-05-28.html">https://grails.org/blog/2016-05-28.html</a></li>
-</ul>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-02-09.jpg)'>
- <a href='https://grails.org/blog/2018-02-09.html'>
- <h3>February 9, 2018</h3>
- <h2>Webinar: Developing React Apps with Grails® 3</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2017-11-21.jpg)'>
- <a href='https://grails.org/blog/2017-11-21.html'>
- <h3>November 21, 2017</h3>
- <h2>Grails® React Profiles</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2017-10-30.html'>
- <h3>October 30, 2017</h3>
- <h2>Quickcast #8: Grails® React Profile</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-11-14.html">https://grails.apache.org/blog/2016-11-14.html</a></p>
</body>
</html>
diff --git a/blog/2016-12-14.html b/blog/2016-12-14.html
index bc2c9480c1..fc718c0ff7 100644
--- a/blog/2016-12-14.html
+++ b/blog/2016-12-14.html
@@ -1,282 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>G3 Summit 2016 Wrap-up!</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="G3 Summit 2016 Wrap-up!" />
- <meta name="date" content="December 14, 2016" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='G3 Summit 2016 Wrap-up!'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='G3 Summit 2016 Wrap-up!'/>
- <meta property='og:description' content='G3 Summit 2016 Wrap-up!'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2016-12-14.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>G3 Summit 2016 Wrap-up!</h1>
-<p><span class="author">By Will Buck<br/> Ryan Vanderwerf<br/> Zachary Klein<br/> and Søren Berg Glasius</span></p>
-<p><span class="date">December 14, 2016</span></p>
-<p><img src="2016-12-14-img01.jpg" alt="The OCI Grails team at G3 Summit 2016" /></p>
-<p>Last month, nearly the entire <a href="https://objectcomputing.com/products/2gm-team">2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team</a> from [Object Computing, Inc.] (https://objectcomputing.com/) (OCI) converged on Fort Lauderdale for the inaugural edition of the G3 Summit, the conference for the Apache Groovy, Grails framework, and Gradle Community. The event is organized by <a href="https://www.nofluffjuststuff.com/home/main">No Fluff Just Stuff</a> and is a fantas [...]
-<p>OCI team members presented over 30 workshops and breakout sessions during the event, in addition to socializing with attendees between sessions and after hours. We’ve asked a few team members to share their experiences at the conference. We hope you will join us next year!</p>
-<h2>Will Buck, Software Engineer</h2>
-<p>For me, the inaugural G3 Summit was a hit! The Groovy community is always great to get together with and this event was no exception. I thought the Westin Beach in Fort Lauderdale was a fantastic venue with great food, the keynotes were all exciting and informative, and the presentation blocks were all packed with quality information that got me fired up to try things out on personal and work projects.</p>
-<p><img src="2016-12-14-img02.jpg" alt="Keynote presentation at G3 Summit 2016" /></p>
-<p>Highlights of the event for me were:</p>
-<ul>
-<li>Iván Lopez’s session on Docker, which had an amazingly well put together sample project that he did a great job touring in his presentation</li>
-<li>Jack Frosch’s session on microservices, which also had a wonderful sample project out on Github and really helped me "put the pieces together" on Netflix’s OSS in this space (Zuul, Eureka, and Hystrics)</li>
-<li><a href="https://twitter.com/groovypuzzlers">Groovy Puzzlers</a> (my first time getting to attend one, hilarious "technical" comedy routine)</li>
-<li>Magician Michael Carducci making James Kleeh’s ring disappear during his magic routine at the closing happy hour</li>
-<li>The Single-Page Application "breakout" session on Tuesday, which was a great discussion of real problems attendees were having in their workplaces and ways we’d collectively found to solve them. This in particular was huge for me, as a big reason I joined the OCI Grails team was to hear from OSS users and think about ways I could contribute to solutions that anyone could enjoy</li>
-<li><strong>Swimming in the Atlantic</strong> after the conference ended, which I don’t think I’ve ever done</li>
-<li>The mealtime conversations about getting Grails apps into the workplace, personal stories about life as a software developer, and children’s fascination with Villains (I found another kindred spirit whose daughter wants to be Darth Vader!)</li>
-</ul>
-<p>Jay Zimmerman and the NFJS tour crew have the kinks worked out on throwing a great conference event and G3 Summit was no exception. I’d highly recommend this to both regulars of the Groovy community and newcomers interested in learning all the great things in our ecosystem!</p>
-<p><img src="2016-12-14-img03.jpg" alt="One highlight of the conference: swimming in the Atlantic Ocean!" /></p>
-<h2>Søren Glasius, Software Engineer</h2>
-<p>This first edition of the G3 Summit was a blast. When traveling to a conference from winter cold Denmark, going to Florida was great.</p>
-<p>I arrived early and had a chance to cruise with Ívan and Álvaro from the OCI Grails Team in a <a href="https://twitter.com/ilopmar/status/802889186906808320">yellow Ford Mustang Convertible</a>.</p>
-<p>But it wasn't all fun and games. The conference was a four-day show of Groovy-ness. The first day was packed with workshops where the attendees had a chance to get in depth knowledge on their favorite G* technology.</p>
-<p>Tuesday kicked off with an insightful keynote by <strong>Guillaume Laforge</strong> covering the current state of <a href="https://groovy-lang.org/">Apache Groovy</a>, followed by Graeme Rocher showing the <a href="https://guides.grails.org/">new Grails Guides portal</a> and the new <a href="https://start.grails.org/#/index">Grails Application Forge</a>. The keynotes were followed by great talks throughout the day.</p>
-<p>On Wednesday I gave two talks: "<a href="https://www.youtube.com/watch?v=ZXRklokhxuE">Get to Know the Grails framework</a>" and "<a href="https://www.youtube.com/watch?v=RuK90qD6RJU">Tour de Plugin</a>," and on Thursday I gave a talk named "<a href="https://www.youtube.com/watch?v=T0sxNY1_GFg">Fields Plugin - Deep Dive</a>" (see links for screencasts).</p>
-<p>My personal favorite experience was when sat down and talked to a (former?) Ruby on Rails developer, who wanted to start using the Grails framework in his projects. To see the smile on his face when he saw Grails apps shine and when he realized that the journey from Rails to Grails apps would be much easier than he had anticipated.</p>
-<p>For me, G3 Summit was well worth the travel from Europe. Thank you to Jay Zimmerman for inviting me to the show, and to his crew who did a great job putting on a great show. I look forward to next year’s edition of G3 Summit.</p>
-<h2>Zachary Klein, Software Engineer</h2>
-<p>The inaugural G3 Summit was a unique and amazing event. The NFJS crew know how to put together a <strong>first-class conference</strong>, and this was no exception. The speaker line-up was very strong, and from the first workshops till the closing sessions there was no shortage of high-quality content.</p>
-<p>Highlights for me would be:</p>
-<ul>
-<li>Venkat Subramaniam’s "Programming Groovy with Java 8" and “Functional Programming for Groovy Programmers”</li>
-<li>Presentations from my OCI colleagues
-<ul>
-<li>James Kleeh. "Angular Scaffolding” and "Creating Custom Profiles"</li>
-<li>Jack Frosch. "Building a Microservice Federation"</li>
-</ul>
-</li>
-</ul>
-<p><img src="2016-12-14-img04.jpg" alt="All-Star Panel" /></p>
-<p>The two "all-star" panel discussions were lively and informative, with a wide-range of topics ranging from the future of Groovy/Grails/Gradle to how we as developers can improve our skills and stay abreast of the new developments in our field. Last but not least, the interactions between sessions with attendees and speakers were a fresh and welcome reminder of the strength and welcoming nature of the Groovy community – you’re all a great bunch of folks to work with!</p>
-<h2>Ryan Vanderwerf, Software Engineer</h2>
-<p>SpringOne2GX has turned into G3 Summit! Groovy, Grails framework and Gradle represent the largest base of G(Groovy)-based tech in the space, but there are so many other projects that are also popular. Jay Zimmerman kicked this one off with his extreme professionalism as all of his NFJS conferences with perfect execution. I was glad to see many new and many familiar faces this year. The venue was nice and right on the beach!</p>
-<p><img src="2016-12-14-img05.jpg" alt="Ryan Vanderwerf on the beach at G3 Summit 2016" /></p>
-<p>Things were small and friendly which allowed open conversations with everyone at the two mixers/happy hours on the roof top. I stuck my head in on workshop day in all of the rooms, they were very well attended, especially for 7 hour workshops!</p>
-<p>I spent most of my time at Dan Wood’s <a href="https://ratpack.io/">Ratpack</a> workshop. He started off in Java for the first few lessons then went improvisational by switching things to Groovy on the fly. I am sure it was way less typing - but in doing things in Java he removed some magic so you would see what is really going on with the framework. I enjoyed it and learned new things!</p>
-<p>That night were was a great kick-off keynote by Venkat Subramaniam and a cocktail reception afterwards.</p>
-<p>On Tuesday the conference was in full swing, with Guillaume Laforge giving a great opening keynote, and Graeme Rocher following up with all of the new and exciting things coming from the Grails team and community. They include:</p>
-<ul>
-<li>The <a href="https://start.grails.org/#/index">Grails Application Forge</a></li>
-<li>Work towards a micro-service profile</li>
-<li>New profile support for Angular and React</li>
-<li>Plans for Grails 3.3</li>
-<li>Many GORM improvements</li>
-</ul>
-<p><img src="2016-12-14-img06.jpg" alt="Paul King presenting Groovy – the Awesome Parts" /></p>
-<p>The day followed with 90 minute sessions by:</p>
-<ul>
-<li>Paul King ("Groovy - the Awesome Parts")</li>
-<li>Jeff Scott Brown (“Runtime Metaprogramming”)</li>
-<li>Ken Kousen (Grails 3 workshop)</li>
-<li>Ivan Lopez (“Dockerize your Grails apps!”)</li>
-<li>Raju Gandi (“Gradle from The Ground Up”)</li>
-</ul>
-<p><img src="2016-12-14-img07.jpg" alt="Jeff Brown presenting Testing Grails 3" /></p>
-<p>After lunch more sessions by:</p>
-<ul>
-<li>Venkat Subramaniam ("Java 8 and Groovy")</li>
-<li>Guillaume Laforge (“What Can You Learn from <a href="https://glaforge.appspot.com/article/analyzing-gradle-grails-and-apache-groovy-source-code-hosted-on-github-with-bigquery">Groovy source files on Github</a>”)</li>
-<li>Alvaro Sanchez-Mariscal (“Mastering Grails 3 Plugins”)</li>
-<li>Jeff Scott Brown (“Testing Grails 3”)</li>
-<li>Gary Hale (“Gradle Worse Practices”)</li>
-</ul>
-<p>Plus a Grails Roadmap Q&A session by Graeme Rocher</p>
-<p>The OCI Grails team organized several informal Q&A sessions throughout the day where people could come and go and ask more detailed questions that wouldn’t fit during a talk. Lots of interesting people came and voiced their opinions, asked for advice, and shared what they were doing or wanted to do.</p>
-<p>Finishing the day was:</p>
-<ul>
-<li>"GORM Inside and Out" by Graeme Rocher</li>
-<li>Paul King with a “Deep Dive into AST Transforms”</li>
-<li>Jeff Scott Brown with “Grails 3 for Spring Boot Developers”</li>
-<li>James Kleeh with “Angular Scaffolding”</li>
-<li>Jon Schneider with "Distributed Refactoring at <a href="https://www.netflix.com/">Netflix</a>”</li>
-</ul>
-<p>That slot was hard for me to choose because I hadn’t seen most of them before; I went to Paul's AST talk, which did not disappoint.</p>
-<p>Tuesday wrapped up with a keynote by Gradle founder and CEO Hans Dockter, in which he announced many new features around wrangling dependencies, such as substitution and replacement. After that was a panel discussion and audience Q&A.</p>
-<p>On Wednesday the conference got going full force with great talks by:</p>
-<ul>
-<li>Jack Frosch sharing Java to Groovy experiences</li>
-<li>David Clark with high-performance Groovy</li>
-<li>Søren Glasius with "Get to Know Grails"</li>
-<li>James Kleeh with “Creating Custom Profiles”</li>
-<li>Ken Kousen on “Gradle Recipes for Android”</li>
-</ul>
-<p>I attended James Kleeh’s talk on custom profiles, which had a lot of good information he put together and documented while building the Angular profiles.</p>
-<p>Next up was:</p>
-<ul>
-<li>Dan Wood with an "Intro to Ratpack"</li>
-<li>Venkat with “Typing in Groovy”</li>
-<li>Jeff Scott Brown with “Monitoring and Metrics for Grails”</li>
-<li>Jack Frosch with “Building a Microservice Federation”</li>
-<li>Chip Dickson and Charles Walker doing a joint talk on “Gradle Migration Blueprints”</li>
-</ul>
-<p>After lunch we had:</p>
-<ul>
-<li>David Clark on “Modern Groovy DSLs”</li>
-<li>Venkat on Spock</li>
-<li>Jeff Scott Brown on “Restful Grails 3”</li>
-<li>Alvaro on “Grails apps, Angular and Spring Security”</li>
-<li>Ethan Hall on Linkedin usage of Gradle</li>
-<li>and yet another informational Q&A Session with SPA (I hung out there to learn myself!)</li>
-</ul>
-<p>The talks just keep on coming all the way until 6:30 - this is a marathon!</p>
-<p>Next slot is:</p>
-<ul>
-<li>Dan Woods with "Groovy in the Cloud"</li>
-<li>Ivan Lopez with Groovy Annotations</li>
-<li>Jeff Scott Brown with “Polyglot Development with Grails apps”</li>
-<li>Zachary Klein with “Using React and Grails 3”</li>
-<li>Scott Hickey with Mutual of Omaha and Jenkins</li>
-<li>A GORM Q&A Session.</li>
-</ul>
-<p>Last slot of talks I gave a new version of my “Alexa Tell my I’m Groovy” where I shared all of the latest efforts my friend Lee Fox and I did with overhaul of the Java SDK which the Grails Plugin and Lazybones Lambda use to make Skills quickly. I demoed the various types of apps/Skills you can make and shared how I made them.</p>
-<p>David Clark had a “Concurrent Groovy” talk at the same time, Colin Harrington had a talk on “Grails View Layer”, Søren Glasius on “Tour de Plugin”, Zak Klein and Will Buck on “Grails apps, Gradle and Node.js”, and Grails 3.2 Q&A session.</p>
-<p>We wrapped up with a great great “Groovy Puzzlers” Season 3 session with Baruch Sadorgursky and Guillaume Laforge, and finally another nice cocktail reception!</p>
-<p>The last day ended a bit slow, with breakfast and panel discussion, followed by a single slot of sessions.</p>
-<p>I gave my talk "Getting Groovy with Google Glass and Android Wear" - by this time it seems most people went home. However, those who came participated in a great discussion about Glass, Wear, modifying cars, and home automation, which I enjoyed.</p>
-<p>Venkat gave a Functional Programming talk, Ken a talk on functional testing with Geb, Søren a talk on <a href="https://github.com/grails-fields-plugin/grails-fields">the Fields plugin</a>, Michael Carducci with CI on Gradle/Jenkins, and Jeff held a Grails Upgrade Q&A Session.</p>
-<p>We finished up the conference with lunch, which was a nice touch at the end I don’t normally see at conferences!</p>
-<p><img src="2016-12-14-img08.jpg" alt="The OCI Grails team enjoying post-conference feast" /></p>
-<p>Overall it was a great conference and would love to see even more attendance next year. I think the 90 minute format is great for a deeper dive into the tech instead of a overview at 60 minutes. The venue is great for nice weather and folks up north getting a break from the cold.</p>
-<p>The last night several teammates went out for Cuban food, which was delicious! On Friday Ivan, Alvaro and I walked around the marina areas and had a nice Italian lunch before hopping on a plane back to Austin.</p>
-<p>I hope to see everyone and more new faces next year!!!</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-03-introducing-grails-6-2-3.html'>
- <h3>January 3, 2025</h3>
- <h2>Introducing Grails Framework 6.2.3 Release</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-02-grails-community-rockstar-fredley.html'>
- <h3>January 2, 2025</h3>
- <h2>James Fredley Named 2025 Grails® Rock Star</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2016-12-14.html">https://grails.apache.org/blog/2016-12-14.html</a></p>
</body>
</html>
diff --git a/blog/2017-01-20-1.html b/blog/2017-01-20-1.html
index a69d451de8..07644a4aa5 100644
--- a/blog/2017-01-20-1.html
+++ b/blog/2017-01-20-1.html
@@ -1,159 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Quickcast #3: Multi-Project Builds</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="In this Quickcast, Grails® framework co-founder, Graeme Rocher, walks you through multi-project builds in Grails apps." />
- <meta name="date" content="January 20, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='player'/><meta name='twitter:player' content='https://www.youtube.com/embed/yNA0ce5fG9s' />
-<meta name='twitter:player:width' content='560' />
-<meta name='twitter:player:height' content='315' />
-
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='In this Quickcast, Grails® framework co-founder, Graeme Rocher, walks you through multi-project builds in Grails apps.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Quickcast #3: Multi-Project Builds'/>
- <meta property='og:description' content='In this Quickcast, Grails® framework co-founder, Graeme Rocher, walks you through multi-project builds in Grails apps.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-01-20-1.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Quickcast #3: Multi-Project Builds</h1>
-<p><span class="author">By Graeme Rocher</span></p>
-<p><span class="date">January 20, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a></p>
-<p>In this video, Grails<sup>®</sup> framework co-founder Graeme Rocher walks you through multi-project builds in Grails apps.</p>
-<p>The Grails framework does a few handy things with multi-project builds and plugins, not the least of which being that Grails compiles your plugins first and puts the class and resources of those plugins directly in the classpath. This lets you make changes to your plugins and instantly see those changes in your build.</p>
-<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
-<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/yNA0ce5fG9s" frameborder="0"></iframe>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2019-01-30.html'>
- <h3>January 30, 2019</h3>
- <h2>Quickcast #12: Building Grails® Applications ...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-1.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #10: Debugging Grails® Apps</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-2.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #11: Grails® Profiling with YourKit</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-01-20-1.html">https://grails.apache.org/blog/2017-01-20-1.html</a></p>
</body>
</html>
diff --git a/blog/2017-01-20-2.html b/blog/2017-01-20-2.html
index 4462276835..dab097c847 100644
--- a/blog/2017-01-20-2.html
+++ b/blog/2017-01-20-2.html
@@ -1,159 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Quickcast #4: Angular Scaffolding</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="This tutorial demonstrates how to have the Grails® framework set up a REST endpoint and all the Angular modules needed to get a web app running." />
- <meta name="date" content="January 20, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='player'/><meta name='twitter:player' content='https://www.youtube.com/embed/tT4BdlRFAis' />
-<meta name='twitter:player:width' content='560' />
-<meta name='twitter:player:height' content='315' />
-
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='This tutorial demonstrates how to have the Grails® framework set up a REST endpoint and all the Angular modules needed to get a web app running.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Quickcast #4: Angular Scaffolding'/>
- <meta property='og:description' content='This tutorial demonstrates how to have the Grails® framework set up a REST endpoint and all the Angular modules needed to get a web app running.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-01-20-2.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Quickcast #4: Angular Scaffolding</h1>
-<p><span class="author">By James Kleeh</span></p>
-<p><span class="date">January 20, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a> <a href="https://grails.org/blog/tag/rest.html"><span class="hashtag">#rest</span></a></p>
-<p>In this Quickcast, 2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#kleeh">James Kleeh</a>, walks you through the process of using the Angular scaffolding for Grails apps to build a fully functional web app, using a simple blog format for demonstration.</p>
-<p>The tutorial explains how to have the Grails framework set up a REST endpoint and all the Angular modules needed to get the web app running.</p>
-<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
-<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/tT4BdlRFAis" frameborder="0"></iframe>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2019-01-30.html'>
- <h3>January 30, 2019</h3>
- <h2>Quickcast #12: Building Grails® Applications ...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-1.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #10: Debugging Grails® Apps</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-2.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #11: Grails® Profiling with YourKit</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-01-20-2.html">https://grails.apache.org/blog/2017-01-20-2.html</a></p>
</body>
</html>
diff --git a/blog/2017-01-20-3.html b/blog/2017-01-20-3.html
index f388dc5972..ffc32f0cd2 100644
--- a/blog/2017-01-20-3.html
+++ b/blog/2017-01-20-3.html
@@ -1,160 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Quickcast #5: Retrieving Runtime Config Values in Grails® 3</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Jeff Scott Brown highlights some of the great features of the Grails Framework." />
- <meta name="date" content="January 20, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='player'/><meta name='twitter:player' content='https://www.youtube.com/embed/Qw5hjwT9EOc' />
-<meta name='twitter:player:width' content='560' />
-<meta name='twitter:player:height' content='315' />
-
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Jeff Scott Brown highlights some of the great features of the Grails Framework.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Quickcast #5: Retrieving Runtime Config Values in Grails® 3'/>
- <meta property='og:description' content='Jeff Scott Brown highlights some of the great features of the Grails Framework.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-01-20-3.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Quickcast #5: Retrieving Runtime Config Values in Grails® 3</h1>
-<p><span class="author">By Jeff Scott Brown</span></p>
-<p><span class="date">January 20, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a></p>
-<p>In this short video tutorial, Grails<sup>®</sup> framework co-founder, <a href="https://objectcomputing.com/products/2gm-team#brown">Jeff Scott Brown</a>, highlights some of the great features of the Grails framework.</p>
-<p>In fewer than 18 minutes, Jeff describes several techniques for retrieving configuration values at runtime and discusses the pros and cons of each. Visit <a href="https://objectcomputing.com/news/2016/08/31/retrieving-config-values-grails-3">this Grails blog post</a> for an accompanying article.</p>
-<p>For this Quickcast, you’ll need no more than a basic understanding of the Grails framework.</p>
-<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
-<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/Qw5hjwT9EOc" frameborder="0"></iframe>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2019-01-30.html'>
- <h3>January 30, 2019</h3>
- <h2>Quickcast #12: Building Grails® Applications ...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-1.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #10: Debugging Grails® Apps</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-2.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #11: Grails® Profiling with YourKit</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-01-20-3.html">https://grails.apache.org/blog/2017-01-20-3.html</a></p>
</body>
</html>
diff --git a/blog/2017-01-20-4.html b/blog/2017-01-20-4.html
index fd8e9b392d..45b2906ba8 100644
--- a/blog/2017-01-20-4.html
+++ b/blog/2017-01-20-4.html
@@ -1,160 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Quickcast #6: Developing Grails® 3 Applications with IntelliJ IDEA</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="In the sixth Grails Quickcast, Grails framework co-founder, Jeff Scott Brown, introduces several tips and tricks related to building Grails 3 applications in IDEA." />
- <meta name="date" content="January 20, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='player'/><meta name='twitter:player' content='https://www.youtube.com/embed/XsCCsTRdezw' />
-<meta name='twitter:player:width' content='560' />
-<meta name='twitter:player:height' content='315' />
-
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='In the sixth Grails Quickcast, Grails framework co-founder, Jeff Scott Brown, introduces several tips and tricks related to building Grails 3 applications in IDEA.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Quickcast #6: Developing Grails® 3 Applications with IntelliJ IDEA'/>
- <meta property='og:description' content='In the sixth Grails Quickcast, Grails framework co-founder, Jeff Scott Brown, introduces several tips and tricks related to building Grails 3 applications in IDEA.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-01-20-4.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Quickcast #6: Developing Grails® 3 Applications with IntelliJ IDEA</h1>
-<p><span class="author">By Jeff Scott Brown</span></p>
-<p><span class="date">January 20, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a></p>
-<p>Grails<sup>®</sup> 3 is a high-productivity framework for building web applications for the JVM.</p>
-<p>IntelliJ IDEA is a high-productivity Integrated Development Environment (IDE) for building a variety of application types. IDEA has always had great support for building Grails applications and, in particular, has the best support of any IDE for developing with Grails 3.</p>
-<p>In this 20-minute video, Grails framework co-founder, <a href="https://objectcomputing.com/products/2gm-team#brown">Jeff Scott Brown</a>, introduces several tips and tricks related to building Grails 3 applications in IDEA.</p>
-<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
-<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/XsCCsTRdezw" frameborder="0"></iframe>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2019-01-30.html'>
- <h3>January 30, 2019</h3>
- <h2>Quickcast #12: Building Grails® Applications ...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-1.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #10: Debugging Grails® Apps</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-2.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #11: Grails® Profiling with YourKit</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-01-20-4.html">https://grails.apache.org/blog/2017-01-20-4.html</a></p>
</body>
</html>
diff --git a/blog/2017-03-27.html b/blog/2017-03-27.html
index b069c25166..d15a452467 100644
--- a/blog/2017-03-27.html
+++ b/blog/2017-03-27.html
@@ -1,176 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>GORM 6.1 Released</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Discover GORM 6.1 features - Multi-Tenancy, JPA Annotations, Bean Validation API, Support for Neo4j" />
- <meta name="date" content="March 27, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Discover GORM 6.1 features - Multi-Tenancy, JPA Annotations, Bean Validation API, Support for Neo4j'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='GORM 6.1 Released'/>
- <meta property='og:description' content='Discover GORM 6.1 features - Multi-Tenancy, JPA Annotations, Bean Validation API, Support for Neo4j'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-03-27.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>GORM 6.1 Released</h1>
-<p><span class="author">By Graeme Rocher</span></p>
-<p><span class="date">March 27, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/release.html"><span class="hashtag">#release</span></a></p>
-<p>Today, <a href="https://objectcomputing.com/products/2gm-team">the Grails<sup>®</sup> team</a> at <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) is pleased to announce the release of <a href="https://gorm.grails.org/6.1.x/">GORM 6.1 GA</a>.</p>
-<p>This release includes <a href="https://gorm.grails.org/latest/whatsNew/manual/index.html">a number of new and exciting features</a> that we are happy to share with you today. Notably:</p>
-<ul>
-<li><a href="https://gorm.grails.org/6.1.x/hibernate/manual/index.html#dataServices">GORM Data Services</a> allow you to easily define interfaces or abstract classes that are automatically implemented for you at compile time.</li>
-<li>Multi-Tenancy AST Transformations</li>
-<li>Support for JPA annotations and Bean Validation API annotations</li>
-<li>Package Scanning for easier unit testing</li>
-<li>Support for Hibernate 5.2+</li>
-<li>Automatic HQL escaping for GString queries</li>
-<li>Support for MongoDB 3.4 and the new Decimal128 Type</li>
-<li>Support for Neo4j 3.1 and the Neo4j 1.2 Bolt Java Driver</li>
-<li>Massive improvements to the Neo4j support including support for relationship entities, paths and more.</li>
-</ul>
-<p>There is too much goodness to go through all of it in a blog post, so I encourage you to read the <a href="https://gorm.grails.org/latest/whatsNew/manual/index.html">release notes</a> and check out the dedicated documentation for each implementation:</p>
-<ul>
-<li><a href="https://gorm.grails.org/6.1.x/hibernate/manual/index.html#releaseHistory">GORM for Hibernate</a></li>
-<li><a href="https://gorm.grails.org/6.1.x/mongodb/manual/index.html#releaseNotes">GORM for MongoDB</a></li>
-<li><a href="https://gorm.grails.org/6.1.x/neo4j/manual/index.html#releaseNotes">GORM for Neo4j</a></li>
-</ul>
-<p>Or alternatively come see my talk about GORM 6.1 in person at Greach in Madrid!</p>
-<p>GORM 6.1 will become the default version of GORM to be used in the upcoming Grails 3.3, in the meantime you can use GORM 6.1 in Grails 3.2 simply by changing the <code>gormVersion</code> setting in <code>gradle.properties</code>:</p>
-<pre><code class="language-groovy">gormVersion=6.1.0.RELEASE
-</code></pre>
-<p>To celebrate the release we have prepared the first of a series of new guides to cover GORM 6.1. Among the many new features are huge improvements to support Neo4j. Using the official Neo4j sample application, the new guide describes how you can <a href="https://guides.grails.org/neo4j-movies/guide/index.html">build a graph application with the Grails framework, GORM 6.1 and Neo4j</a>! Enjoy!</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2019-07-11.jpg)'>
- <a href='https://grails.org/blog/2019-07-11.html'>
- <h3>July 11, 2019</h3>
- <h2>Grails® 4 GA Released</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2019-02-19.jpg)'>
- <a href='https://grails.org/blog/2019-02-19.html'>
- <h3>February 19, 2019</h3>
- <h2>Grails® 4 Milestone 1 Released</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2017-07-26.jpg)'>
- <a href='https://grails.org/blog/2017-07-26.html'>
- <h3>July 26, 2017</h3>
- <h2>Grails® 3.3 GA Released</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-03-27.html">https://grails.apache.org/blog/2017-03-27.html</a></p>
</body>
</html>
diff --git a/blog/2017-04-02.html b/blog/2017-04-02.html
index f087c36850..b1a0329c3f 100644
--- a/blog/2017-04-02.html
+++ b/blog/2017-04-02.html
@@ -1,230 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>How to Add Build Info to Your Project</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="How to include information about your build in your application" />
- <meta name="date" content="April 2, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='How to include information about your build in your application'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='How to Add Build Info to Your Project'/>
- <meta property='og:description' content='How to include information about your build in your application'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-04-02.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>How to Add Build Info to Your Project</h1>
-<p><span class="author">By Søren Berg Glasius & Colin Harrington</span></p>
-<p><span class="date">April 2, 2017</span></p>
-<h2>Introduction</h2>
-<p>When you build and run Grails<sup>®</sup> 3 applications, often you may want to know about the build environment via the running application.</p>
-<p>Since the early days of the Grails framework, we were able to add arbitrary properties to the <code>application.properties</code> file. The Grails framework provides this information through the <code>grails.util.Metadata</code> class, and for views this is easily made available through the tag.</p>
-<p>Since Grails 3 is built with <a href="https://gradle.org/">Gradle</a>, the old <code>application.properties</code> is no longer in use. Instead we'll add properties to <code>grails.build.info</code></p>
-<h2>The Basics</h2>
-<p>When you build/run your Grails applications, one of tasks that Gradle always executes is <code>buildProperties</code>. This task takes a small set of build information from your project and places it in a file, which the Grails <code>Metadata</code> class later reads. This file is located in <code>META-INF</code> and is named <code>grails.build.info</code>.</p>
-<p>At build time, you can find this file at <code>build/resources/main/META-INF/grails.build.info</code>. The contents of this file looks like:</p>
-<pre><code class="language-property">#Thu, 02 Feb 2017 15:30:37 +0100
-
-info.app.version=0.1
-info.app.name=metadata
-grails.env=production
-info.app.grailsVersion=3.2.5
-</code></pre>
-<p>This info primarily comes from <code>build.gradle</code> and <code>gradle.properties</code> (the curious can check out the source code in <a href="https://github.com/grails/grails-core/blob/6c85ec239aa8cc4a9f646bb345c70c327ddb2dbc/grails-gradle-plugin/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy#L179">grails-core</a>). This file will be part of your final application when you build your <code>.jar</code> or <code>.war</code> file.</p>
-<p>In a <code>.gsp</code>, this information is available by using the meta tag like this: (see the <a href="https://gsp.grails.org/latest/guide/index.html#tags">tag</a> documentation).</p>
-<h2>Adding More Information to <code>grails.build.info</code></h2>
-<p>With the Gradle build system, it is possible to hook into the build process and execute our own code. In this case we want Gradle to complete writing <code>grails.build.info</code>, and then we want to add additional properties to the file.</p>
-<p>To accomplish this, add the following snippet to <code>build.gradle</code> in your project:</p>
-<pre><code class="language-groovy">buildProperties.doLast {
- // Find the right file
- File grailsBuildInfoFile = it.outputs.files.files.find { it.name == 'grails.build.info' }
- if(!grailsBuildInfoFile) return // No need to continue if the file is not there
- Properties properties = new Properties()
- // Read properties from the file
- grailsBuildInfoFile.withInputStream {
- properties.load(it)
- }
- // Add new properties from various sources
- properties.setProperty('build.time', new Date().format("yyyy-MM-dd HH:mm:ss"))
- // Get a System property
- properties.setProperty('build.java.version', System.getProperty('java.version'))
- // Get the host name where the build was created
- properties.setProperty('build.host', InetAddress.localHost.hostName)
- // Add property set by your CI (in this case Bamboo)
- Map<String, String> env = System.getenv()
- if(env.bamboo_buildNumber) {
- properties.setProperty('build.number', env.bamboo_buildNumber)
- properties.setProperty('build.git.revision', env.bamboo_planRepository_revision)
- properties.setProperty('build.git.branch', env.bamboo_planRepository_branch)
- }
- // Write the properties back to the file
- grailsBuildInfoFile.withOutputStream {
- properties.store(it,null)
- }
-}
-</code></pre>
-<p>This example shows:</p>
-<ul>
-<li>How to set <code>build.time</code> from the time that the build was executed</li>
-<li>How to set values from <code>System.properties</code></li>
-<li>How to get your build host name</li>
-<li>How to read environment variables set by your build server (in the above example by <a href="https://www.atlassian.com/software/bamboo">Atlassian Bamboo</a>)</li>
-</ul>
-<p>Now that we have this build information captured in <code>grails.build.info</code>, we can show it in our application in a <code>.gsp</code> page.</p>
-<p>For example:</p>
-<pre><code class="language-html"><table>
- <thead>
- <tr><th>Name</th><th>Value</th></tr>
- </thead>
- <tbody>
- <tr><td>Build time</td><td><g:meta name="build.time"></g:meta>></td></tr>
- <tr><td>Build java version</td><td><g:meta name="build.java.version"></g:meta>></td></tr>
- <tr><td>Build host</td><td><g:meta name="build.host"></g:meta>></td></tr>
- </tbody>
-</table>
-</code></pre>
-<p>... and so on.</p>
-<blockquote>
-<p>NOTE: If you use the Spring Boot Actuator endpoints, you can write <a href="https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html#production-ready-application-info-custom">your own custom InfoContributor</a> that uses Grails <code>Metadata</code>!</p>
-<p>Alternatively, you can leverage the <a href="https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html#production-ready-application-info-autoconfigure">Auto-configured InfoContributors</a> to:</p>
-<ul>
-<li><a href="https://guides.grails.org/adding-commit-info/guide/index.html">add git commit info</a>
--expose build info by copying <code>grails.build.info</code> to a <code>build-info.properties</code> file (<a href="https://github.com/spring-projects/spring-boot/blob/v1.5.2.RELEASE/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/BuildInfoContributor.java">BuildInfoContributor</a>)</li>
-<li>expose environment info by configuring properties starting with <code>'info.'</code> such as <code>'info.app.name'</code> (<a href="https://github.com/spring-projects/spring-boot/blob/v1.5.2.RELEASE/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/EnvironmentInfoContributor.java">EnvironmentInfoContributor</a>)</li>
-</ul>
-</blockquote>
-<h2>Conclusion</h2>
-<p>This blog-post shows how you can easily add build information to your Grails 3 application by leveraging the tasks already available within the Gradle build, and how you can show them in your application.</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-03-introducing-grails-6-2-3.html'>
- <h3>January 3, 2025</h3>
- <h2>Introducing Grails Framework 6.2.3 Release</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-02-grails-community-rockstar-fredley.html'>
- <h3>January 2, 2025</h3>
- <h2>James Fredley Named 2025 Grails® Rock Star</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-04-02.html">https://grails.apache.org/blog/2017-04-02.html</a></p>
</body>
</html>
diff --git a/blog/2017-04-12.html b/blog/2017-04-12.html
index 11036319b4..7046314494 100644
--- a/blog/2017-04-12.html
+++ b/blog/2017-04-12.html
@@ -1,256 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Grails® Angular Profiles</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Grails® framework provided Angular profiles have been renamed" />
- <meta name="date" content="April 12, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Grails® framework provided Angular profiles have been renamed'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Grails® Angular Profiles'/>
- <meta property='og:description' content='Grails® framework provided Angular profiles have been renamed'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-04-12.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Grails® Angular Profiles</h1>
-<p><span class="author">By James Kleeh</span></p>
-<p><span class="date">April 12, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/angular.html"><span class="hashtag">#angular</span></a></p>
-<p>In order to be consistent with the Angular team's guidelines on naming conventions, we have renamed the Angular profiles that the Grails<sup>®</sup> framework provides. This change will take affect in Grails 3.2.9. Any existing applications will not be impacted by this change. This will only affect your project if you create a new application with Grails 3.2.9 or above, or if you upgrade an existing application.</p>
-<p>Previously we had:</p>
-<table>
-<thead>
-<tr><th>Name</th><th>Latest Version</th><th>Repo Location</th><th>Angular Versions Supported</th></tr>
-</thead>
-<tbody>
-<tr><td>angular</td><td>3.2.2</td><td>https://github.com/grails-profiles/angular</td><td>1.x</td></tr>
-<tr><td>angular2</td><td>1.0.5</td><td>https://github.com/grails-profiles/angular2</td><td>2.x</td></tr>
-</tbody>
-</table>
-<p>The "angular" profile was renamed to "angularjs." Then the "angular2" profile was renamed to "angular."</p>
-<p>Since "angularjs" is a new module, we restarted the version to 1.0.0.</p>
-<p>Since "angular" already exists, the version had to be higher than the current version. Since the existing version is 3.2.2, we chose 4.0.0. That also happens to fall in line with the Angular version supported, however the new profile may not follow the Angular version it supports.</p>
-<p>Now we have:</p>
-<table>
-<thead>
-<tr><th>Name</th><th>Latest Version</th><th>Repo Location</th><th>Angular Versions Supported</th></tr>
-</thead>
-<tbody>
-<tr><td>angularjs</td><td>1.0.0</td><td>https://github.com/grails-profiles/angularjs</td><td>1.x</td></tr>
-<tr><td>angular</td><td>4.0.0</td><td>https://github.com/grails-profiles/angular</td><td>4.x</td></tr>
-</tbody>
-</table>
-<h2>Potential Issues Caused by This Change</h2>
-<h3><a href="https://github.com/grails-profiles/angularjs">Angular Profile</a></h3>
-<p>If you have an existing application created with the "angular" profile, you are using the profile for Angular 1.x.</p>
-<pre><code class="language-groovy">dependencies {
- profile org.grails.profiles:angular
-}
-</code></pre>
-<p>Since the Grails framework manages the version of the profile for you, if you were to upgrade to a newer version of the Grails framework, you will get the newer version of the angular profile. That means that previously you had the Angular 1.x profile and after upgrading, you will have the Angular 4.x profile.</p>
-<p>Fortunately the change will not change the behavior of your application in any way. The only problem you may encounter is if you attempt to use the commands provided by the AngularJS profile. You will find the commands (<code>create-ng-controller</code>, <code>create-ng-directive</code>, etc) won't work as they exist in the "angularjs" profile, while you have the "angular" profile.</p>
-<p>To get the commands working again, simply change the dependency to "angularjs".</p>
-<pre><code class="language-groovy">dependencies {
- profile org.grails.profiles:angular //Change to "angularjs"
-}
-</code></pre>
-<p>In addition, you should change the profile set in the configuration.</p>
-<pre><code class="language-yaml">grails:
- profile: angular //Change to "angularjs"
-</code></pre>
-<h3><a href="https://github.com/grails-profiles/angular">Angular2 Profile</a></h3>
-<p>If you have an existing application with the "angular2" profile and you upgrade to Grails 3.2.9 and above, you will find Gradle can't find the dependency because the Grails framework is no longer providing a version for that dependency. To fix the problem, simply change the dependency in <code>build.gradle</code>.</p>
-<pre><code class="language-groovy"> dependencies {
- profile org.grails.profiles:angular2 //Change to "angular"
- }
-</code></pre>
-<p>In addition, you should change the profile set in the configuration.</p>
-<pre><code class="language-yaml">grails:
- profile: angular2 // Change to "angular"
-</code></pre>
-<h2>Scaffolding Plugin Changes</h2>
-<p>In addition to the profiles, the plugins that provide scaffolding also needed to be renamed in the same manner.</p>
-<blockquote>
-<p>NOTE: At the time of this post, the Angular 2.x+ scaffolding is still in a release candidate stage.</p>
-</blockquote>
-<p>Before:</p>
-<table>
-<thead>
-<tr><th>Name</th><th>Latest Version</th><th>Repo Location</th><th>Angular Versions Supported</th></tr>
-</thead>
-<tbody>
-<tr><td>angular-scaffolding</td><td>1.0.1</td><td>https://github.com/grails-plugins/grails-angular-scaffolding</td><td>1.x</td></tr>
-<tr><td>angular2-scaffolding</td><td>1.0.0.RC1</td><td>https://github.com/grails-plugins/grails-angular2-scaffolding</td><td>2.x +</td></tr>
-</tbody>
-</table>
-<p>After:</p>
-<table>
-<thead>
-<tr><th>Name</th><th>Latest Version</th><th>Repo Location</th><th>Angular Versions Supported</th></tr>
-</thead>
-<tbody>
-<tr><td>angularjs-scaffolding</td><td>1.0.3</td><td>https://github.com/grails-plugins/grails-angularjs-scaffolding</td><td>1.x</td></tr>
-<tr><td>angular-scaffolding</td><td>2.0.0.RC1</td><td>https://github.com/grails-plugins/grails-angular-scaffolding</td><td>2.x +</td></tr>
-</tbody>
-</table>
-<p>The only change necessary is to update your <code>build.gradle</code>.</p>
-<h3><a href="https://github.com/grails-plugins/grails-angular-scaffolding">Angular 2.x +</a></h3>
-<pre><code class="language-groovy">buildscript {
- dependencies {
- //Change to "angular-scaffolding:2.0.0.RC1"
- classpath org.grails.plugins:angular2-scaffolding:1.0.0.RC1
- }
-}
-dependencies {
- //Change to "angular-scaffolding:2.0.0.RC1"
- compile org.grails.plugins:angular2-scaffolding:1.0.0.RC1
-}
-</code></pre>
-<h3><a href="https://github.com/grails-plugins/grails-angularjs-scaffolding">Angular 1.x</a></h3>
-<pre><code class="language-groovy">buildscript {
- dependencies {
- //Change to "angularjs-scaffolding:1.0.3"
- classpath org.grails.plugins:angular-scaffolding:1.0.1
- }
-}
-dependencies {
- //Change to "angularjs-scaffolding:1.0.3"
- compile org.grails.plugins:angular-scaffolding:1.0.1
-}
-</code></pre>
-<h2>Conclusion</h2>
-<p>The goal of this change was to make determining which profile/scaffolding plugin should be used less confusing in the future. If you encounter any problems as a result of this change that were not expected, please file an issue.</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-01-03-introducing-grails-6-2-3.html'>
- <h3>January 3, 2025</h3>
- <h2>Introducing Grails Framework 6.2.3 Release</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2016-07-06.jpg)'>
- <a href='https://grails.org/blog/2016-07-06.html'>
- <h3>July 6, 2016</h3>
- <h2>Grails® Angular Scaffolding</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-04-12.html">https://grails.apache.org/blog/2017-04-12.html</a></p>
</body>
</html>
diff --git a/blog/2017-05-09.html b/blog/2017-05-09.html
index 09f7540d33..d523e807cd 100644
--- a/blog/2017-05-09.html
+++ b/blog/2017-05-09.html
@@ -1,220 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Why You Should Avoid Using Autowiring for Grails® Domain Classes</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Autowiring a service into a domain class can have a big performance impact." />
- <meta name="date" content="May 9, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Autowiring a service into a domain class can have a big performance impact.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Why You Should Avoid Using Autowiring for Grails® Domain Classes'/>
- <meta property='og:description' content='Autowiring a service into a domain class can have a big performance impact.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-05-09.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Why You Should Avoid Using Autowiring for Grails® Domain Classes</h1>
-<p><span class="author">By Sergio Del Amo Caballero</span></p>
-<p><span class="date">May 9, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/gorm.html"><span class="hashtag">#gorm</span></a></p>
-<p>You should not inject services into a domain class.</p>
-<p>Why?</p>
-<p>Autowiring a service into a domain class can have a big performance impact.</p>
-<p>Imagine you query 1,000 records from a database, and those records are mapped into a GORM entities. Injecting a service into each of those 1,000 GORM entities will have a performance cost.</p>
-<p>Thus, <a href="https://github.com/grails/grails-core/releases/tag/v3.2.8">starting with Grails<sup>®</sup> 3.2.8</a> auto wiring of GORM entities is disabled when you create an app from scratch. In Grails 3.3.0 or above it is disabled by default.</p>
-<p>Let me illustrate this with an example.</p>
-<p>The following code will not get the service <em>greetingService</em> injected into a domain class unless you enable auto wiring.</p>
-<pre><code class="language-groovy">package demo
-
-class Greeter {
-
- def greetingService
-
- String name
-
- String sayHello() {
- "${name}${greetingService.sayHi()}"
- }
-}
-package demo
-
-class GreetingService {
- String sayHi() {
- 'Hello'
- }
-}
-
-package demo
-
-class HelloController {
-
- def index() {
- def person = new Greeter(name: 'Sergio')
-
- render person.sayHello()
- }
-}
-</code></pre>
-<p>If you are autowiring services into your domain instances as in the above example, you will need to re-enable it.</p>
-<p>For versions of Grails 3.3.0 or above, you can turn on autowire on a single domain class:</p>
-<p>grails-app/domain/demo/Book.groovy</p>
-<pre><code class="language-groovy">class Book {
- BookService bookService
-
- String name
-
- static mapping = {
- autowire true
- }
- ...
- ..
- .
-}
-</code></pre>
-<p>You can turn on autowire for all your domain classes using the <a href="https://gorm.grails.org/latest/hibernate/manual/index.html#_the_default_mapping_constraints%5BDefault">Default Mapping</a> setting:</p>
-<p>grails-app/conf/application.groovy</p>
-<pre><code class="language-groovy">grails.gorm.default.mapping = {
- autowire true
-}
-</code></pre>
-<p>For versions below Grails 3.3.0, you can re-enable it changing the <em>grails.gorm.autowire</em> configuration parameter.</p>
-<p>grails-app/conf/application.yml</p>
-<pre><code>grails:
- gorm:
- autowire: true
-</code></pre>
-<p><strong>If Spring autowiring of domain instances is enabled, read performance will degrade.</strong></p>
-<p>Try to avoid the injection of services in domain classes. the Grails framework has an excellent services layer. You should place your business logic there.</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-10-02.jpg)'>
- <a href='https://grails.org/blog/2018-10-02.html'>
- <h3>October 2, 2018</h3>
- <h2>Grails® Domain Read-Only Attribute</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-04-05.jpg)'>
- <a href='https://grails.org/blog/2018-04-05.html'>
- <h3>April 5, 2018</h3>
- <h2>Introducing the Grails® 3 GORM Logical Delete...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-03-09.jpg)'>
- <a href='https://grails.org/blog/2018-03-09.html'>
- <h3>March 9, 2018</h3>
- <h2>Webinar: Build a Better API with GORM & Graph...</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-05-09.html">https://grails.apache.org/blog/2017-05-09.html</a></p>
</body>
</html>
diff --git a/blog/2017-06-27.html b/blog/2017-06-27.html
index 918dd5b06d..bebde78f7b 100644
--- a/blog/2017-06-27.html
+++ b/blog/2017-06-27.html
@@ -1,251 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Checked Exceptions Rollback Transactions Since GORM 6.0.0</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Learn about the changes to exceptions rollback behaviour introduced in GORM 6." />
- <meta name="date" content="June 27, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Learn about the changes to exceptions rollback behaviour introduced in GORM 6.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Checked Exceptions Rollback Transactions Since GORM 6.0.0'/>
- <meta property='og:description' content='Learn about the changes to exceptions rollback behaviour introduced in GORM 6.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
- <link rel='stylesheet' href='https://grails.orghttps://grails.org/stylesheets/prism.css'/>
- <script src='https://grails.org/javascripts/prism.js'></script>
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-06-27.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Checked Exceptions Rollback Transactions Since GORM 6.0.0</h1>
-<p><span class="author">By Sergio Del Amo Caballero</span></p>
-<p><span class="date">June 27, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/gorm.html"><span class="hashtag">#gorm</span></a></p>
-<p><a href="https://pragprog.com/book/vslg2/programming-groovy-2">Programming Groovy 2</a>:</p>
-<blockquote>
-<p>Groovy has less ceremony than Java. That's crystal-clear in exception handling. Java forces us to handle checked exceptions. Groovy does not force us to handle exceptions that we don't want to handle or that are inappropriate at the current level of code. Any exception we don't handle is automatically passed on to a higher level.</p>
-</blockquote>
-<p>Although the distinction between checked exceptions and runtime exceptions in Groovy is blurred, <strong>GORM versions before 6.0.0 did not roll back transactions for checked <code>Exceptions</code></strong>. However, they rollbacked transactions for runtime exceptions.</p>
-<p>Grails<sup>®</sup> 3.2.0 shipped with GORM 6.0.0. One of the changes introduced by GORM 6.0.0 is that if a transactional method throws an <code>Exception</code> (both checked or runtime exception), the transaction will automatically be rolled back. Thus, same behavior for checked and runtime exceptions as you may expect in Groovy.</p>
-<p>The previous behavior is better illustrated with an example:</p>
-<p>Given a Checked Exception</p>
-<pre><code class="language-groovy">package demo
-
-import groovy.transform.CompileStatic
-
-@CompileStatic
-class CustomCheckedException extends Exception {
-}
-</code></pre>
-<p>and a RuntimeException</p>
-<pre><code class="language-groovy">package demo
-
-import groovy.transform.CompileStatic
-
-@CompileStatic
-class CustomRuntimeException extends RuntimeException {
-}
-</code></pre>
-<p>and the next service:</p>
-<pre><code class="language-groovy">package demo
-
-import grails.transaction.Transactional
-import groovy.transform.CompileStatic
-
-@CompileStatic
-@Transactional
-class BookService {
-
- void addNewBookChecked() {
- def book = new Book(name: 'The definitive guide to grails 3')
- book.save()
- throw new CustomCheckedException()
- }
-
- void addNewBookRuntime() {
- def book = new Book(name: 'The definitive guide to grails 3')
- book.save()
- throw new CustomRuntimeException()
- }
-
- void addNewBookRegular() {
- def book = new Book(name: 'The definitive guide to grails 2')
- book.save()
- }
-
- @Transactional(readOnly = true)
- int count() {
- Book.where { }.count() as int
- }
-}
-</code></pre>
-<p>The next specification passes for versions of GORM 6.0.0 or beyond.</p>
-<pre><code class="language-groovy">package demo
-
-import spock.lang.Specification
-import spock.lang.Subject
-import grails.test.mixin.integration.Integration
-
-@Integration
-class BookServiceIntegrationSpec extends Specification {
-
- @Subject
- BookService bookService
-
- def "calling a service method which does not throw any exception results in adding a new book"() {
- when:
- bookService.addNewBookRegular()
-
- then:
- bookService.count() == old(bookService.count()) + 1
- }
-
- def "calling a service method which throws a runtime exception, rollback transaction and it does not add a new book"() {
- when:
- bookService.addNewBookRuntime()
-
- then:
- thrown CustomRuntimeException
- bookService.count() == old(bookService.count())
- }
-
- // Fails with GORM versions < 6.0.0
- def "calling a service method which throws a Checked exception, rollback transaction and it does not add a new book"() {
- when:
- bookService.addNewBookChecked()
-
- then:
- thrown CustomCheckedException
- bookService.count() == old(bookService.count())
- }
-}
-</code></pre>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-10-02.jpg)'>
- <a href='https://grails.org/blog/2018-10-02.html'>
- <h3>October 2, 2018</h3>
- <h2>Grails® Domain Read-Only Attribute</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-04-05.jpg)'>
- <a href='https://grails.org/blog/2018-04-05.html'>
- <h3>April 5, 2018</h3>
- <h2>Introducing the Grails® 3 GORM Logical Delete...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-03-09.jpg)'>
- <a href='https://grails.org/blog/2018-03-09.html'>
- <h3>March 9, 2018</h3>
- <h2>Webinar: Build a Better API with GORM & Graph...</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-06-27.html">https://grails.apache.org/blog/2017-06-27.html</a></p>
</body>
</html>
diff --git a/blog/2017-06-28.html b/blog/2017-06-28.html
index b28454ab77..6cd356d503 100644
--- a/blog/2017-06-28.html
+++ b/blog/2017-06-28.html
@@ -1,221 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Running a Grails® 3 App With a Self-Signed SSL Certificate</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Learn the steps involved in generating and configuring a self-signed certificate with your Grails app." />
- <meta name="date" content="June 28, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Learn the steps involved in generating and configuring a self-signed certificate with your Grails app.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Running a Grails® 3 App With a Self-Signed SSL Certificate'/>
- <meta property='og:description' content='Learn the steps involved in generating and configuring a self-signed certificate with your Grails app.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-06-28.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Running a Grails® 3 App With a Self-Signed SSL Certificate</h1>
-<p><span class="author">By Zachary Klein</span></p>
-<p><span class="date">June 28, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/ssl.html"><span class="hashtag">#ssl</span></a> <a href="https://grails.org/blog/tag/deployment.html"><span class="hashtag">#deployment</span></a></p>
-<p>The <a href="https://docs.grails.org/latest/ref/Command%20Line/run-app.html">Grails<sup>®</sup> <em>run-app</em> command documentation</a> describes how to use the <em>-https</em> flag to serve your app over HTTPS.</p>
-<blockquote>
-<p>https - Start an HTTPS server (on port 8443 by default) alongside the main server. Just to be clear, the application will be accessible via HTTPS and HTTP. A self-signed key will be generated. Intended for development use only.</p>
-</blockquote>
-<p>If you run the following command:</p>
-<pre><code>grails run-app -https // with HTTPS
-</code></pre>
-<p>Your app will be served at <em>https://localhost:8443</em></p>
-<p>However, as stated in the documentation, the <em>https</em> flag is intended for development use only. In real-world applications, an SSL certificate from a <a href="https://en.wikipedia.org/wiki/Certificate_authority">Certificate Authority</a>, would be used to verify your application's identity with clients. However, it is also possible to generate a self-signed certificate for testing purposes. A self-signed certificate doesn't provide the identity protection that a CA offers, but [...]
-<h2>Generate Your Self-Signed SSL Certificate</h2>
-<p>You can generate a self-signed certificate using the <a href="https://www.openssl.org/"><code>openssl</code></a> command-line utility. This is installed by default on most Unix-based OS's, and can be installed on <a href="https://sourceforge.net/projects/openssl-for-windows/">Windows</a> as well.</p>
-<p>We can use <code>openssl</code>'s <code>req</code> command to create a self-signed certificate:</p>
-<p><code>openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365</code></p>
-<p>We're using several command options:</p>
-<ul>
-<li><strong>x509</strong> This option outputs a self-signed certificate instead of a certificate request.</li>
-<li><strong>newkey</strong> This option creates a new certificate request and a new private key. <code>rsa:nbits</code>, where <code>nbits</code> is the number of bits, generates an RSA key nbits in size.</li>
-<li><strong>keyout</strong> This specifies the filename for the the newly created private key.</li>
-<li><strong>out</strong> This specifies the output filename to write the certificate</li>
-<li><strong>days</strong> When used with the <code>-x509</code> option, <code>days</code> specifies the number of days to certify the certificate for. The default is 30.</li>
-</ul>
-<p>You can learn about other <code>req</code> options by running <code>man req</code></p>
-<p>The previous command will prompt you to supply metadata about the certificate, such as Country, Organization, etc. Moreover, it will ask you to provide a PEM pass phrase. Enter a random password and keep it safe; we will need in the next step.</p>
-<p>Now you have you self-signed certificate. Unfortunately the Grails framework (and Spring Boot) doesn’t support the PEM format directly. Instead, we need to use the PKCS12 format for our keys. Fortunately, there is another <code>openssl</code> command to make the conversion:</p>
-<p><code>openssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12 -name tomcat -caname root</code></p>
-<p>Again, we're using a few options:</p>
-<ul>
-<li><strong>export</strong> This option specifies that a PKCS#12 file will be created rather than parsed.</li>
-<li><strong>name</strong> This specifies the certificate entry for the certificate and private key. When we edit our <code>application.yml</code> file, we will use this name as the <code>keyAlias</code></li>
-<li><strong>in</strong> This specifies filename of the PKCS#12 file to be parsed.</li>
-<li><strong>inkey</strong> File from which to read the private key.</li>
-<li><strong>caname</strong> This specifies the "friendly name" for other certificates</li>
-</ul>
-<p>You can learn more about the <code>pkcs121</code> command by running <code>man pks12</code></p>
-<h2>Modify Grails Configuration to Use the Certificate</h2>
-<p>Update <code>grails-app/conf/application.yml</code> with the following lines:</p>
-<pre><code>server:
- port: 8443
- ssl:
- keyStore: /certificates/keystore.p12
- keyStorePassword: secret
- keyAlias: tomcat
-</code></pre>
-<p>You can read more about pkcs121 by running <code>man pks12</code></p>
-<h2>Using Java KeyStores</h2>
-<p>If you are deploying your app to a container like Tomcat, you will need to use a <a href="https://en.wikipedia.org/wiki/Keystore">Java KeyStore (JKS)</a> to store your SSL certificate. We can use the <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html"><code>keytool</code></a> command-line utility (provided by Java) to create a JKS from our PKCS#12 keystore.</p>
-<p>Use the <code>importkeystore</code> command to import and create the new keystore:</p>
-<pre><code>keytool -importkeystore -srckeystore keystore.p12 -srcstoretype pkcs12 -srcalias tomcat -destkeystore keystore.jks -deststoretype jks -deststorepass secret -destalias tomcat
-</code></pre>
-<ul>
-<li><strong>srckeystore</strong> Source keystore (in our case, <code>keystore.p12</code>)</li>
-<li><strong>srcstoretype</strong> Source keystore type</li>
-<li><strong>srcalias</strong> Certificate entry in the source keystore (in our case, "tomcat")</li>
-<li><strong>destkeystore</strong> File name for the JKS</li>
-<li><strong>deststoretype</strong> Keystore type (JKS)</li>
-<li><strong>deststorepass</strong> Password for the JKS</li>
-<li><strong>destalias</strong> Certificate entry in the JKS</li>
-</ul>
-<p>Now we can update our <code>application.yml</code> to use the JKS file instead of the PKCS#12 keystore.</p>
-<pre><code>server:
- port: 8443
- ssl:
- enabled: true
- keyStore: /certificates/keystore.jks
- keyStorePassword: secret
- keyAlias: tomcat
-</code></pre>
-<h2>Example:</h2>
-<p><a href="https://github.com/grails-samples/grails-ssl">Github Repository with a Grails sample application</a></p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-3.png)'>
- <a href='https://grails.org/blog/2025-03-05-grails-7-m3.html'>
- <h3>March 5, 2025</h3>
- <h2>Grails 7.0.0-M3 - Release Announcement</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2019-01-07.jpg)'>
- <a href='https://grails.org/blog/2019-01-07.html'>
- <h3>January 7, 2019</h3>
- <h2>SDKMAN! with Travis</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2016-11-10.jpg)'>
- <a href='https://grails.org/blog/2016-11-10.html'>
- <h3>November 10, 2016</h3>
- <h2>Deploying Grails® 3.2 to JBoss 7.1 EAP</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-06-28.html">https://grails.apache.org/blog/2017-06-28.html</a></p>
</body>
</html>
diff --git a/blog/2017-07-12.html b/blog/2017-07-12.html
index 2f11e8cd54..cc64888591 100644
--- a/blog/2017-07-12.html
+++ b/blog/2017-07-12.html
@@ -1,160 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Quickcast #7: Logging with Grails® 3</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Sergio del Amo Caballero introduces several tips and tricks related to logging with a Grails 3 application." />
- <meta name="date" content="July 12, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='player'/><meta name='twitter:player' content='https://www.youtube.com/embed/3TppFy3lq1A' />
-<meta name='twitter:player:width' content='560' />
-<meta name='twitter:player:height' content='315' />
-
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Sergio del Amo Caballero introduces several tips and tricks related to logging with a Grails 3 application.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Quickcast #7: Logging with Grails® 3'/>
- <meta property='og:description' content='Sergio del Amo Caballero introduces several tips and tricks related to logging with a Grails 3 application.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-07-12.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Quickcast #7: Logging with Grails® 3</h1>
-<p><span class="author">By Sergio del Amo Caballero</span></p>
-<p><span class="date">July 12, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a></p>
-<p>In this 20-minute video, 2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#caballero">Sergio del Amo Caballero</a>, introduces several tips and tricks related to logging with a Grails 3 application.</p>
-<p>Sergio discusses changes to logger names in Grails 3.3 and things to bear in mind when logging in Grails artifacts and Groovy POGOs.</p>
-<p>Moreover, he explains the benefits of using Slf4j, parameterized logging, how to configure rolling logging, how to use an external configuration file, and more.</p>
-<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
-<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/3TppFy3lq1A" frameborder="0"></iframe>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2019-01-30.html'>
- <h3>January 30, 2019</h3>
- <h2>Quickcast #12: Building Grails® Applications ...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-1.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #10: Debugging Grails® Apps</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-2.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #11: Grails® Profiling with YourKit</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-07-12.html">https://grails.apache.org/blog/2017-07-12.html</a></p>
</body>
</html>
diff --git a/blog/2017-07-26.html b/blog/2017-07-26.html
index e34d5bcebd..838a079940 100644
--- a/blog/2017-07-26.html
+++ b/blog/2017-07-26.html
@@ -1,158 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Grails® 3.3 GA Released</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Grails 3.3. release announcement" />
- <meta name="date" content="July 26, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Grails 3.3. release announcement'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Grails® 3.3 GA Released'/>
- <meta property='og:description' content='Grails 3.3. release announcement'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-07-26.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Grails® 3.3 GA Released</h1>
-<p><span class="author">By Graeme Rocher</span></p>
-<p><span class="date">July 26, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/release.html"><span class="hashtag">#release</span></a></p>
-<p>Just in time for <a href="https://gr8conf.us/">Gr8Conf US</a>, the <a href="https://objectcomputing.com/products/2gm-team">Grails<sup>®</sup> team</a> at <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) is pleased to announce the release of <a href="https://docs.grails.org/3.3.x/">Grails 3.3 GA</a>.</p>
-<p>Grails 3.3 includes a number of significant improvements, most notably to GORM with GORM 6.1, which we <a href="https://grails.org/blog/2017-03-27.html">released earlier</a> in order to gather feedback from Grails 3.2.x users.</p>
-<p>GORM 6.1 includes some real breakthrough innovations, including <a href="https://gorm.grails.org/6.1.x/hibernate/manual/index.html#dataServices">Data Services</a> that allow you to define interfaces that are automatically implemented and work seamlessly with GORM's multi-tenancy features.</p>
-<p>Other highlights of Grails 3.3 include the new <a href="https://async.grails.org/latest/guide/index.html#events">EventBus</a> abstraction which integrates with existing reactive libraries such as RxJava. Events are also for the first time transaction aware so that consumers are only notified if the surrounding transaction is successful, which simplifies code greatly.</p>
-<p>Overall there is an abundance of new features and improvements that developers will be able to take advantage of, from the <a href="https://testing.grails.org/">new testing framework</a> to improvemments to <a href="https://views.grails.org/latest/">JSON Views</a>.</p>
-<p>All of these new features and more are covered in the <a href="https://docs.grails.org/3.3.x/guide/introduction.html#whatsNew">What's New guide</a>. Thanks to the Grails community who contributed greatly to making the release a success and we look forward <a href="https://github.com/grails/grails-core/issues">to your feedback</a>!</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2019-07-11.jpg)'>
- <a href='https://grails.org/blog/2019-07-11.html'>
- <h3>July 11, 2019</h3>
- <h2>Grails® 4 GA Released</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2019-02-19.jpg)'>
- <a href='https://grails.org/blog/2019-02-19.html'>
- <h3>February 19, 2019</h3>
- <h2>Grails® 4 Milestone 1 Released</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2017-03-27.jpg)'>
- <a href='https://grails.org/blog/2017-03-27.html'>
- <h3>March 27, 2017</h3>
- <h2>GORM 6.1 Released</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-07-26.html">https://grails.apache.org/blog/2017-07-26.html</a></p>
</body>
</html>
diff --git a/blog/2017-10-30.html b/blog/2017-10-30.html
index 6adeae9f6a..d95a00aca0 100644
--- a/blog/2017-10-30.html
+++ b/blog/2017-10-30.html
@@ -1,160 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Quickcast #8: Grails® React Profile</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Zachary Klein demonstrates how to use the Grails® 3 React profile to build Grails applications with a React frontend." />
- <meta name="date" content="October 30, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='player'/><meta name='twitter:player' content='https://www.youtube.com/embed/JVLn7kWkjp0' />
-<meta name='twitter:player:width' content='560' />
-<meta name='twitter:player:height' content='315' />
-
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Zachary Klein demonstrates how to use the Grails® 3 React profile to build Grails applications with a React frontend.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Quickcast #8: Grails® React Profile'/>
- <meta property='og:description' content='Zachary Klein demonstrates how to use the Grails® 3 React profile to build Grails applications with a React frontend.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-10-30.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Quickcast #8: Grails® React Profile</h1>
-<p><span class="author">By Zachary Klein</span></p>
-<p><span class="date">October 30, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a> <a href="https://grails.org/blog/tag/react.html"><span class="hashtag">#react</span></a></p>
-<p>In this short video tutorial, 2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#klein-z">Zachary Klein</a>, demonstrates how to use the Grails 3 React profile to build Grails applications with a React frontend.</p>
-<p>In particular, Zak shows you how to create a single project build, which allows you to mix React code with common Grails-view technologies, such as GSP.</p>
-<p>Moreover, he discusses the different Gradle tasks bundled with the profile and the typical workflow you may use while using it.</p>
-<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
-<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/JVLn7kWkjp0" frameborder="0"></iframe>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2019-01-30.html'>
- <h3>January 30, 2019</h3>
- <h2>Quickcast #12: Building Grails® Applications ...</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-1.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #10: Debugging Grails® Apps</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2018-08-22-2.html'>
- <h3>August 22, 2018</h3>
- <h2>Quickcast #11: Grails® Profiling with YourKit</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-10-30.html">https://grails.apache.org/blog/2017-10-30.html</a></p>
</body>
</html>
diff --git a/blog/2017-11-09.html b/blog/2017-11-09.html
index 7ac76193c2..0784707791 100644
--- a/blog/2017-11-09.html
+++ b/blog/2017-11-09.html
@@ -1,173 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Webinar: Grails® 3 for Spring Developers</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Discover Grails® from the perspective of a Spring developer in this 75-minute webinar presented by Jeff Brown and Josh Long." />
- <meta name="date" content="November 9, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='player'/><meta name='twitter:player' content='https://www.youtube.com/embed/71Avk4IcEPs' />
-<meta name='twitter:player:width' content='560' />
-<meta name='twitter:player:height' content='315' />
-
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Discover Grails® from the perspective of a Spring developer in this 75-minute webinar presented by Jeff Brown and Josh Long.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Webinar: Grails® 3 for Spring Developers'/>
- <meta property='og:description' content='Discover Grails® from the perspective of a Spring developer in this 75-minute webinar presented by Jeff Brown and Josh Long.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-11-09.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Webinar: Grails® 3 for Spring Developers</h1>
-<p><span class="author">By Jeff Scott Brown & Josh Long</span></p>
-<p><span class="date">November 9, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a></p>
-<h2>Overview</h2>
-<p>Grails<sup>®</sup> 3 is a full stack framework built on top of Spring Boot. In addition to all of the capabilities offered by Boot, developers using Grails 3 benefit from the enormous productivity gains and other features (e.g., GORM, Profiles, etc.) that Grails 3 packs in!</p>
-<p>In this webinar, Spring Developer Advocate, Josh Long (@starbuxman), and Grails framework co-founder, Jeff Scott Brown (@jeffscottbrown), introduce the Grails framework from the perspective of a Spring developer and demonstrate how these awesome technologies play so well together.</p>
-<p>The session will be of interest to anyone looking to build robust JVM web applications with high productivity, while keeping the application code expressive and simple.</p>
-<p>Grails developers will find many interesting tips and tricks during the demonstrations but no prior experience with the Grails framework is necessary.</p>
-<h2>Outline</h2>
-<p>The following topics are covered in this webinar:</p>
-<ul>
-<li>Quick Intro to Spring & the Grails framework</li>
-<li>REST</li>
-<li>JSON views</li>
-<li>Testing</li>
-<li>Plugins</li>
-<li>Security</li>
-<li>Deployment</li>
-<li>Customizing Spring Boot in a Grails app</li>
-</ul>
-<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/71Avk4IcEPs" frameborder="0"></iframe>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-1.png)'>
- <a href='https://grails.org/blog/2021-05-21-2gm-town-hall-q2.html'>
- <h3>May 21, 2021</h3>
- <h2>2GM Town Hall Meeting: 2021 Q2</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/grails-blog-index-4.png)'>
- <a href='https://grails.org/blog/2021-02-05-2gm-town-hall-q1.html'>
- <h3>February 5, 2021</h3>
- <h2>Webinar: 2GM TOWN HALL MEETING: 2021 Q1</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2019-12-20.jpg)'>
- <a href='https://grails.org/blog/2019-12-20.html'>
- <h3>December 20, 2019</h3>
- <h2>Webinar: Grails® 4 Upgrade</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-11-09.html">https://grails.apache.org/blog/2017-11-09.html</a></p>
</body>
</html>
diff --git a/blog/2017-11-21.html b/blog/2017-11-21.html
index 82194ac92e..5558e6422d 100644
--- a/blog/2017-11-21.html
+++ b/blog/2017-11-21.html
@@ -1,180 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Grails® React Profiles</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="Learn about Grails® React-Webpack profile" />
- <meta name="date" content="November 21, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='Learn about Grails® React-Webpack profile'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Grails® React Profiles'/>
- <meta property='og:description' content='Learn about Grails® React-Webpack profile'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-11-21.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Grails® React Profiles</h1>
-<p><span class="author">By Zachary Klein</span></p>
-<p><span class="date">November 21, 2017</span></p>
-<p>Tags: <a href="https://grails.org/blog/tag/react.html"><span class="hashtag">#react</span></a></p>
-<p>As of Grails<sup>®</sup> 3.3.2, there are now two distinct <a href="https://docs.grails.org/latest/guide/profiles.html">Profiles</a> for using <a href="https://reactjs.org/">React</a> in your Grails projects. These profiles are essentially the same as those described in the <a href="https://grails.org/blog/2017-11-21.html">announcement post</a>, with some updates.</p>
-<h2>React-Webpack Profile for Grails apps</h2>
-<p>This profile provides a monolithic project structure with React code embedded within the Grails project. Formerly, to use this version of the profile you had to specific it's version explictly. Now, this profile can be used when creating a new Grails 3.3.2 app like so:</p>
-<pre><code>grails create-app myapp -profile react-weback
-</code></pre>
-<p>You can also choose this project when generating your project from the <a href="https://start.grails.org/">Grails Application Forge</a>, either from the web app or via the API:</p>
-<pre><code>curl -O start.grails.org/myapp.zip -d profile=react-webpack
-</code></pre>
-<p>Besides the convenience of having a distinct name for the project, the new name better reflects the dependence of the <code>react-webpack</code> profile on its parent profile, <code>webpack</code>. You can use the <code>webpack</code> profile directly if you want to pick your own frontend JavaScript libraries in your project.</p>
-<p>The documentation for the <code>react-webpack</code> profile is available at <a href="https://grails-profiles.github.io/react-webpack/latest"><code>https://grails-profiles.github.io/react-webpack/latest</code></a></p>
-<h2>New Start Task</h2>
-<p>The <code>react</code> profile now provides both <code>start</code> and <code>bootRun</code> tasks for the <code>client</code> project. <code>bootRun</code> is intended to be used when running both <code>server</code> and <code>client</code> in parallel; otherwise, the client app can now be started using either <code>./gradlew start</code> or <code>yarn start</code> /<code>npm start</code>.</p>
-<p>The documentation for the <code>react</code> profile is available at <a href="https://grails-profiles.github.io/react/latest"><code>https://grails-profiles.github.io/react/latest</code></a></p>
-<h2>React 16</h2>
-<p>Both the <code>react</code> and <code>react-webpack</code> profiles have been upgraded to use React 16. In addition, the <code>react</code> profile is now using the latest (1.0.17, as of time of writing) release of <a href="https://github.com/facebookincubator/create-react-app"><code>create-react-app</code></a>.</p>
-<h2>Known Issues</h2>
-<p>Both of these profiles (as well as the <code>angular</code> profile) leverage the <a href="https://github.com/node-gradle/gradle-node-plugin">Gradle Node Plugin</a> to wrap the Node.js build tools when running via Grails or Gradle commands.</p>
-<p>Unfortunately, there are a couple of issues with the underlying Gradle task management with this plugin. In particular, the following two issues are known and being investigated:</p>
-<ol>
-<li>Node process sometimes fails to stop when run from Gradle. This is due to an issue in <a href="https://github.com/gradle/gradle/issues/1128">Gradle</a>. You may need to kill the process manually in order to restart the app.</li>
-<li>Errors when running React tests via Gradle. This error seems to be specific to the latest versions of macOS. A related issue has been <a href="https://github.com/facebook/jest/issues/1767">reported against Jest</a>, the testing framework used in this profile for React tests. One workaround is to not use Gradle to manage the Node.js installation - instead, you can install Node manually (or using <a href="https://github.com/objectcomputing/grails-team-blog/blob/gh-pages/_posts/javascri [...]
-</ol>
-<pre><code>node {
- version = '8.7.0'
- yarnVersion = '1.3.2'
- download = false
-</code></pre>
-<p>You can now run the tests either using <code>./gradlew client:test</code>, or <code>yarn test</code>.</p>
- <h2 class='space-above'>
- <span>You might also like ...</span>
- </h2>
- <div class='threecolumns'>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2018-02-09.jpg)'>
- <a href='https://grails.org/blog/2018-02-09.html'>
- <h3>February 9, 2018</h3>
- <h2>Webinar: Developing React Apps with Grails® 3</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/quickcast.jpg)'>
- <a href='https://grails.org/blog/2017-10-30.html'>
- <h3>October 30, 2017</h3>
- <h2>Quickcast #8: Grails® React Profile</h2>
- </a>
-</article></div>
- <div class='column'><article class='blogcard' style='background-image: url(https://grails.org/images/2016-11-14.jpg)'>
- <a href='https://grails.org/blog/2016-11-14.html'>
- <h3>November 14, 2016</h3>
- <h2>Introducing the React Profile for Grails®</h2>
- </a>
-</article></div>
- </div>
- </div>
-</div> </article>
-<footer>
- <div class='content'>
- <div class='ocihometograils'>
- <a href='https://grails.org/foundation/index.html'><img class='' src='https://grails.org/images/foundation-logo-horizontal-orange.svg' alt='Grails Foundation' width='300px' /></a>
- <span style="margin-top:22px;">© 2025 Grails Foundation. All rights reserved.</span>
- </div>
- <nav class='socialmedianav'>
- <ul>
- <li>
- <a href='mailto:info@grails.org'><img class='' src='https://grails.org/images/email.svg' alt='Email Icon' /></a>
- </li>
- <li>
- <a href='https://slack.grails.org'><img class='' src='https://grails.org/images/slack.svg' alt='Slack Icon' /></a>
- </li>
- <li>
- <a href='https://www.youtube.com/@GrailsFramework'><img class='' src='https://grails.org/images/youtube.svg' alt='Youtube Icon' /></a>
- </li>
- <li>
- <a href='https://www.linkedin.com/showcase/official-grails/'><img class='' src='https://grails.org/images/linkedin.svg' alt='LinkedIn Icon' /></a>
- </li>
- <li>
- <a href='https://github.com/grails/'><img class='' src='https://grails.org/images/github.svg' alt='Github Icon' /></a>
- </li>
- <li style="margin-bottom:10px;">
- <a href='https://twitter.com/grailsframework'><img class='' src='https://grails.org/images/x-twitter.svg' alt='Twitter Icon' /></a>
- </li>
- </ul>
- </nav>
- <nav class='partnersnav'><ul>
-
- <li>The Grails framework is Open Source
- <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2 License</a>
- </li>
-
- <li>
- <a href='https://grails.org/privacy-policy.html'>Privacy Policy</a>
- </li>
- <li>
- <a href='https://grails.org/trademark-policy.html'>Trademark Policy & Brand Guidelines</a>
- </li>
- </ul></nav>
- </div>
-</footer><div>
- <script type='text/javascript'>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-82213539-2', 'auto');
- ga('send', 'pageview');
- </script>
-</div>
+<body>
+<p>This page has moved to <a href="https://grails.apache.org/blog/2017-11-21.html">https://grails.apache.org/blog/2017-11-21.html</a></p>
</body>
</html>
diff --git a/blog/2017-11-30.html b/blog/2017-11-30.html
index 2e1eee009f..36693def9d 100644
--- a/blog/2017-11-30.html
+++ b/blog/2017-11-30.html
@@ -1,156 +1,10 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
- <title>Eric Helgeson Named 2017 Grails® Rock Star</title>
- <meta name="keywords" content="grails,jvm,framework,groovy,gradle,spring-boot,gorm" />
- <meta name="description" content="The Grails® Rock Star Award recognizes a member of the Grails Community for his or her outstanding contributions to the success of the Framework." />
- <meta name="date" content="November 30, 2017" />
- <meta name="robots" content="all"/>
- <link rel="alternate" type="application/rss+xml" title="RSS" href="https://grails.org/rss.xml" />
- <meta charset='UTF-8' />
- <link rel='icon' href='https://grails.org/images/favicon.ico'/>
- <meta name='twitter:card' content='summary_large_image'/>
- <meta name='twitter:site' content='@grailsframework'/>
- <meta name='twitter:description' content='The Grails® Rock Star Award recognizes a member of the Grails Community for his or her outstanding contributions to the success of the Framework.'/>
- <meta name='twitter:creator' content='@grailsframework'/>
- <meta property='og:image' content='https://grails.org/images/grails.png'/>
- <meta property='og:image:width' content='300'/>
- <meta property='og:image:height' content='300'/>
- <meta property='og:url' content='https://grails.org'/>
- <meta property='og:title' content='Eric Helgeson Named 2017 Grails® Rock Star'/>
- <meta property='og:description' content='The Grails® Rock Star Award recognizes a member of the Grails Community for his or her outstanding contributions to the success of the Framework.'/>
- <meta property='og:type' content='website'/>
-
- <meta name='viewport' content='width=device-width, initial-scale=1' />
- <link rel='mask-icon' href='https://grails.org/images/grails-pinned-icon.svg' color='feb672' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/screen.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/plugin.css' />
- <link rel='stylesheet' href='https://grails.org/stylesheets/paginate.css' />
- <script src='https://grails.org/javascripts/navigation.js'></script>
- <script src='https://grails.org/javascripts/paginate.js'></script>
-
-
-
- <script src='https://grails.org/javascripts/plugins.js'></script>
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0; url=https://grails.apache.org/blog/2017-11-30.html"/>
</head>
-<body><header class='mainheader'>
- <div class='content'>
- <a href='https://grails.org/index.html'><img class='grailslogo' src='https://grails.org/images/grails_logo.svg' alt='Grails Logo' /></a>
- <a href='javascript:show('topmenus', 'showNavigationLink')' id='showNavigationLink' class='mobile align-center'>Show Navigation</a>
- <div id='topmenus'>
- <nav class='secondarymenu' id='secondarymenu'><ul>
- <li><a href='https://grails.org/casestudies/index.html'>Case Studies</a></li>
- <li><a href='https://grails.org/blog/index.html'>Blog</a></li>
- <li><a href='https://grails.org/learning.html'>Learning</a></li>
- <li><a href='https://grails.org/community.html'>Community</a></li>
- <li><a href='https://grails.org/search.html'>Search</a></li>
- </ul></nav>
- <nav class='mainmenu' id='mainmenu'><ul>
- <li><a href='https://grails.org/documentation.html'>Documentation</a></li>
- <li><a href='https://grails.org/download.html'>Download</a></li>
- <li><a href='https://grails.org/plugins.html'>Plugins</a></li>
- <li><a href='https://guides.grails.org/index.html'>Guides</a></li>
- <li><a href='https://grails.org/foundation/index.html'>Foundation</a></li>
- <li><a href='https://grails.org/faq.html'>FAQ</a></li>
- <li><a href='https://grails.org/support.html'>Support</a></li>
- <li><a href='https://start.grails.org'>Forge App</a></li>
- </ul></nav>
- </div>
- </div>
-</header>
-<article><div class='headerbar chalicesbg'>
- <div class='content'>
- <h1>
- <a href='https://grails.org/blog/index.html'>Grails Blog</a>
- </h1>
- </div>
-</div>
-<div class='content container'>
- <div class='light padded blogpost'><h1>Eric Helgeson Named 2017 Grails® Rock Star</h1>
-<p><span class="author">By Sergio Del Amo Caballero</span></p>
-<p><span class="date">November 30, 2017</span></p>
-<p>The Grails<sup>®</sup> Rock Star Award recognizes a member of the Grails Community for his or her outstanding contributions to the success of the Framework.</p>
-<p>Yesterday at G3 Summit 2017, Eric Helgeson was awarded the Grails Rock Star Award. Eric is the author of the book <a href="https://www.grails3book.com/">Practical Grails 3</a>, and he is often seen in the <a href="https://grails.slack.com/">Grails Slack Community</a> answering and helping other users. Moreover, Eric contributes to the Grails Community with code, plugin development, issues reporting, etc.</p>
... 480718 lines suppressed ...