Closed codeconsole closed 1 month ago
Thank you for the interest in supporting Sitemesh 3. The Grails 6 GA is around the corner. It would be great to have an idea of how much effort is required so we can plan better.
I would request you to help with the development and we might be able to include it in 6.0.0 or 6.1.0.
It would be great to have an idea of how much effort is required so we can plan better.
I took a look at the grails implementation and it looks like there was some customizations requiring some extra classes for Sitemesh 2. I already updated Sitemesh 2 with the fixes and we should be able to at the very least include Sitemesh 2.5 with Grails 6.
I’ll also come up with documentation on migration
I've been digging into the Grails SiteMesh integration and it is a bit more involved than I anticipated. There is a lot of customization and work arounds.
Going from SiteMesh 2.4.2 to SiteMesh 2.5.0 may be challenging due to the introduction of buffering in 2.5.0 which further diverges the Grails custom implementation from the more recent changes. What is most problematic, is that Grails appears to have introduced its own type of buffering as well. https://github.com/sitemesh/sitemesh2/compare/2.4.2...2.5.0-M1
I already released SiteMesh 2.4.3 which slightly reduces the grails-web-sitemesh footprint by removing custom classes that were created as a workarounds to a long standing bug 2.4.2 bugs.
The key difference between Sitemesh 2 and Sitemesh 3 is that Sitemesh 3 is not coupled to any templating system. It is completely decoupled. It is as simple as just adding a single servlet filter that works on top of any view technology.
I've created a sample Spring Boot 2.7 application that demonstrates the integration.
Because of this, migrating Grails to Sitemesh 3 is as simple as injecting the Filter and using a Grails tag library that simply just writes the new Sitemesh 3 tags. This can all be done in a plugin (NOW COMPLETE).
For example, an existing Grails template:
<html lang="en">
<head>
<title><g:layoutTitle default="Hello"/> | World </title>
<g:layoutHead/>
</head>
<body>
<g:layoutBody/>
<g:pageProperty name="page.javascript" />
</body>
</html>
The tag library works by producing Sitemesh 3 tags used by the Sitemesh 3 filter does all the work:
<html lang="en">
<head>
<title><sitemesh:write property='Hello World' /> | Example </title>
<sitemesh:write property='head' />
</head>
<body>
<sitemesh:write property='body'/>
<sitemesh:write property='page.javascript'/>
</body>
</html>
I have already started a Jakarta Branch for SiteMesh 3 which would ease Grails migration to JDK 17.
Migrating from Sitemesh 2 to Sitemesh 3 not only completely decouples Sitemesh from GSP, but it also offers one new powerful feature that GSP has been lacking: Decorator Chaining. With SiteMesh 3, you can apply multiple decorators to a view. For instance something like this:
<meta name="layout" content="my-decorator,my-other-decorator" />
is now allowed.
I would like to see a Grails independent GSP example. It appears work was done on this some time ago, but has not been updated since. I've updated the previous work (codeconsole/grails-boot) to the latest Spring Boot 1.x, but it appears not possible to use with Grails > 3.x due to StandaloneGrailsApplication.java not being included in 3.x? Is there another way to use GSP pages independently?
@puneetbehl I've released SiteMesh 2.4.3 which eliminates work around code from grails-gsp that was needed for SiteMesh 2.4.2 https://github.com/grails/grails-gsp/pull/362
I am willing to release a 2.4.3 Jakarta compliant version of SiteMesh if there is a grails-gsp jdk 17 branch. I am also willing to do whatever development is necessary to make SiteMesh work on that jdk 17 branch. I can have this ready within 1 week from when it is requested or within 1 week of a jdk 17 grails-gsp branch being created.
The only reason I mention this is because I am assuming Sitemesh was a contributing factor in not releasing Jakarta as part of Grails 6.
@puneetbehl I've created a SiteMesh 3 plugin demonstrating the use of SiteMesh 3 in Grails: https://github.com/codeconsole/grails-sitemesh3
All of the SiteMesh 2 code could be deleted from grails-gsp and the plugin will work seamlessly with grails so that all the existing tags work and no changes are necessary to upgrade.
@codeconsole Good job! Thank you for your hard work. Next, I will upgrade to this version. It is said that 2.5 has a significant performance improvement, when will version 2.5.0 be released?
Hello @rainboyan,
yeah, I will be releasing 2.5.0 in the next week or so. I am working hard completely decoupling Grails from SiteMesh. The plan right now is to release the new 3.1.0, submit 2 small pull requests for Grails 6 grais-gsp and grails-core (already complete), merge atlassians latest changes into 2.5.0, then release 2.5.0.
I have released a Grails pull request for 2.4.3, but since I already have Grails working with 3.1.0, I will most likely not update Grails for 2.5.
I have everything ready to go for 6.0.x
This is what I recommend:
Pull Request: Update SiteMesh 2.4.2 to 2.4.3 Pull Request: Decouple grails-gsp from SiteMesh 2
Once these pull requests are complete, either SiteMesh 2.4.3 or SiteMesh 3.1.0 can be used independently with Grails 6.0.x
@codeconsole Thank you for your reply.
I have a couple of questions here,
I have released a Grails pull request for 2.4.3, but since I already have Grails working with 3.1.0, I will most likely not update Grails for 2.5.
I'm not sure, Grails uses Semantic Versioning or not. Now that Grails 6 is already using Sitemesh 2.4, upgrading to 3.1 is clearly a breaking change.
Once these pull requests are complete, either SiteMesh 2 or SiteMesh 3 can be used with Grails 6.0.x
Sitemesh 3 has changed the package name to org.sitemesh
, I don't think Grails 6 can support both versions, maybe a lot of work.
Have you considered creating a Spring Boot Starter for SiteMesh? If so, Spring Boot and Grails, and even Micronaut could use it.
Recently, I've been working on refactoring the ViewResolver implementation for Grails, which is now using other template engines like Groovy MarkupTemplate and Freemarker in Grails applications, thanks to the support already available in Spring Boot.
Finally, have a nice weekend!
@rainboyan nothing is breaking here. I currently am using Grails 6 with SiteMesh 3 in a production environment. SiteMesh 3 is extremely non-invasive and is just a filter so it works with any framework. There are no breaking changes. No customization is needed. All you have to do is install the plugin. Once the 2 pull requests I mentioned above, you don't even need the sitemesh 2 jar installed and grails runs fine.
As a temporary workaround, the plugin also works without the pull requests, but you will still need the sitemesh 2 jar installed. Give it a try.
Modify build.gradle
to use the plugin
repositories {
// ... existing repos here
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
}
dependencies {
implementation("org.sitemesh:grails-plugin-sitemesh3:0.1-SNAPSHOT")
// ... existing dependencies
}
oss snapshots
is needed temporarily until sitemesh 3.1.0 and the plugin are officially released.
Your app is now using SiteMesh 3 and is no longer using SiteMesh 2. NO FURTHER CHANGES NEEDED.
Bonus: You can now enjoy multiple layouts on each page!
For instance, let's use /grails-app/views/layouts/googleAnalyticsLayout.gsp
and /grails-app/views/layouts/main.gsp
:
<html lang="en">
<head>
<meta name="layout" content="googleAnalyticsLayout, main"/>
<title>Home</title>
</head>
Once the following simple Pull Request is accepted, you can use 2.x version of the plugin and add the following to build.gradle
for a smaller footprint:
Pull Request: Decouple grails-gsp from SiteMesh 2
configurations {
all {
exclude group:'opensymphony', module:'sitemesh'
exclude group:'org.grails', module:'grails-web-gsp-taglib'
exclude group:'org.grails', module:'grails-web-sitemesh'
}
}
Hi @codeconsole, thanks for the detailed instructions.
I was looking at the changelog and found that some Sitemesh 3 code was introduced in version 2.4.3, for example under the package com.opensymphony.sitemesh.compatability
, I don't quite understand the reason for doing this, I think in this patch version shouldn't change so much. In my opinion it would be better if it was at 2.6.x, since there is a 2.5.x in between.
but of course it would take a lot of effort to maintain multiple versions like that, after all, Sitemesh hasn't been updated in years.
I have previously completed a 2.4.2 version migration to Jakarta and it works fine, SiteMesh 2 Jakarta version. So, I would not consider upgrading to Sitemesh 3 right away, as there are still a lot of work that needs to be put into refactoring and modifying the GSP itself before I can do that.
I have just upgraded GoBoots to SiteMesh 2.4.3, local tests passed, and everything works fine.
Next step will be 2.5.0.
Thank you @codeconsole
Hi @codeconsole, thanks for the detailed instructions.
I was looking at the changelog and found that some Sitemesh 3 code was introduced in version 2.4.3, for example under the package
com.opensymphony.sitemesh.compatability
, I don't quite understand the reason for doing this, I think in this patch version shouldn't change so much. In my opinion it would be better if it was at 2.6.x, since there is a 2.5.x in between. but of course it would take a lot of effort to maintain multiple versions like that, after all, Sitemesh hasn't been updated in years.
Hello @rainboyan, I don't understand. No SiteMesh 3 code was introduced into 2.4.3. You can see the changes here: https://github.com/sitemesh/sitemesh2/compare/2.4.2..2.4.3
With the plugin, there shouldn't be any refactoring required.
The plugin provides a tag library that overrides the SiteMesh 2 tags with a SiteMesh 3 replacement. I suppose the only caveat would be is if you use the tag g:ifPageProperty
. That is the only tag not supported.
@codeconsole
I see a lot classes under the package com.opensymphony.sitemesh
, adding javadoc @since SiteMesh 3
, so I thought that these classes are from SiteMesh 3.
The refactoring of GSP I mentioned earlier is not related to SiteMesh upgrades.
siteMesh/sitemesh2:master
is not currently fully synchronized with atlassian/sitemesh2:master
, where 2.5-atlassian-10
has some performance improvements for finding head tags, do you have any next update plans?
@rainboyan yeah, those classes haven nothing to do with SiteMesh 3. You can expect 2.5 to be synchronized within the next week.
Right now we are just waiting on @puneetbehl to merge https://github.com/grails/grails-gsp/pull/364 so that it does not depend on the SiteMesh 2 libraries to be installed.
I've clone the sitemesh2/master
code (2.5.x), compiled it locally, built it with my GoBoots (forked Grails), and ran successfully in an old project, everything works fine and looks good.
Thank you @codeconsole
@rainboyan thanks, now that, I'll probably officially 2.5.0 release it within the next week.
I've clone the
sitemesh2/master
code (2.5.x), compiled it locally, built it with my GoBoots (forked Grails), and ran successfully in an old project, everything works fine and looks good.Thank you @codeconsole
@rainboyan, I am not sure how you got 2.5.x working without customizing grails-gsp? 2.5.x is not a drop in replacement for 2.4.x as it requires initializing a SitemeshBuffer
. Neither GSPSitemeshPage or GrailsHTMLPageParser. will work otherwise.
@codeconsole
Oh, I did modify the gsp-related code, mainly to use SitemeshBuffer
, but not to GSPSitemeshPage
, which I haven't tested yet.
I think GSPSitemeshPage
probably needs to be rewritten.
@puneetbehl GroovyPageLayoutFinder
is part of grails-web-sitemesh
which is now a transitive dependency of grails:plugins:gsp
which is what injects groovyPageLayoutFinder
. I believe it is the RestRederer
trait that is causing the issues with some of the unit tests because they do not have grails:plugins:gsp
as a dependency.
I have just been adding grails-web-sitemesh
as a test dependecy because the assumption is that grails-web-sitemesh
will resolve automatically due to any real grails app needing the grails:plugins:gsp
dependency. Is there a situation you know of where a specific type of grails app will not have the grails:plugins:gsp
plugin installed?
@puneetbehl what is the plan for Grails 7? Are you wanting both SiteMesh 2 and SiteMesh 3 support? If you want to get rid of SiteMesh 2 altogether, I am more than happy to submit a pull request with it completely removed from the branch. This of course will be breaking and require new plugin releases to go along with 7 because of it being part of the traits compiled into each plugin (which in my opinion was poor design).
Personally, I am more inclined to remove SiteMesh 2 from Grails 7. But, I would also check with others opinion in the next Grails Engineering Meeting. Thank you for helping us with it.
Apart from this, I tried to reach out to you over the email (scott@alwaysvip.com). Can you please confirm if you actually receive any email from me?
yeah, that's correct. Your email got overlooked. I just replied.
@codeconsole, could you kindly submit the pull-request for removing Sitemesh2? I'm presently engaged in updating Grails Core to Spring Boot 3 and Spring 6. I believe it's necessary to update Grails GSP beforehand as it involves transitioning to Jakarta APIs from javax.servlet
.
@puneetbehl ok, I will look into this.
@puneetbehl https://github.com/grails/grails-gsp/pull/459
We still need a 7.0.x branch for https://github.com/grails/grails-gradle-plugin
Pull Request for core: https://github.com/grails/grails-core/pull/13492
Demo running off of 7.0.x: https://github.com/codeconsole/grails-sitemesh3-demo
I have since released a Jakarta version of sitemesh 2 so I am not opposed to supporting both with Grails 7, but it needs to be further decoupled from Grails such that it is only resolved by including the sitemesh 2 plugin. Currently using sitemesh 3 requires having to use configuration exclusions of the sitemesh2 jars.
@codeconsole Is sitemesh2 going to be maintained going forward?
lol, I would prefer not to maintain it, but I don't mind releasing community contributed fixes.
2.6.0 would be an easy drop in because it is built off of 2.4.x and does not include the 2.5.x changes that Grails is not compatible with. I am thinking about rolling back my removal commit on 7.x branch and then refactoring ResponseRenderer.groovy so it doesn't depend on sitemesh2 specifically. We could have all the sitemesh2 deps resolve with the newly created grails-plugin-sitemesh2.
The main problem is that it is a trait so we don't want the final design to change after 7.x, otherwise plugins dependent on it will break. This isn't an issue now because all plugins are breaking going into 7.x
If I understand things correctly @codeconsole, your excellent work on the sitemesh3-grails-plugin will make it a drop-in replacement for sitemesh2 in Grails 7 rendering sitemesh2 support superfluous.
@matrei yes, but there might be some custom sitemesh2 work that someone is dependent on and I did run into an issue I haven't had a chance to solve.
Feature description
Sitemesh 3 already supports JDK 17 which would make it an easier transition to Grails 7.0.
Since 6.0 is taking a while, I think it should be considered to be part of the 6.0 release.
I could help facilitate the development effort if it is agreed to add it.