Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to Sitemesh 3 #13058

Open
codeconsole opened this issue Jul 4, 2023 · 28 comments
Open

Update to Sitemesh 3 #13058

codeconsole opened this issue Jul 4, 2023 · 28 comments

Comments

@codeconsole
Copy link
Contributor

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.

@puneetbehl
Copy link
Contributor

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.

@aadrian
Copy link

aadrian commented Jul 7, 2023

It would be great to have an idea of how much effort is required so we can plan better.

sitemesh/sitemesh3#77

@codeconsole
Copy link
Contributor Author

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

@codeconsole
Copy link
Contributor Author

codeconsole commented Jul 11, 2023

SiteMesh Upgrade Options

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.

https://github.com/grails/grails-gsp/tree/6.0.x/grails-web-sitemesh/src/main/groovy/org/grails/web/sitemesh

Most Complex - 2.5.0

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.
sitemesh/sitemesh2@2.4.2...2.5.0-M1

Simple - 2.4.3 and Grails 6.0.x ready. - NOW COMPLETE - Pending 1 pull request.

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.

More work - 3.1.0 and Grails 6.0.x ready - NOW COMPLETE - Pending 2 pull requests (Request 1 and Request 2).

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>

Going Further (JDK 17) - Jakarta compatible SiteMesh 3.2 already available.

I have already started a Jakarta Branch for SiteMesh 3 which would ease Grails migration to JDK 17.

Final Thoughts

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?

@codeconsole
Copy link
Contributor Author

codeconsole commented Jul 25, 2023

@puneetbehl
I've released SiteMesh 2.4.3 which eliminates work around code from grails-gsp that was needed for SiteMesh 2.4.2
grails/grails-gsp#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.

@codeconsole
Copy link
Contributor Author

codeconsole commented Jul 27, 2023

@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.

@rainboyan
Copy link
Contributor

@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?

@codeconsole
Copy link
Contributor Author

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.

@codeconsole
Copy link
Contributor Author

codeconsole commented Jul 30, 2023

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

@rainboyan
Copy link
Contributor

@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!

@codeconsole
Copy link
Contributor Author

codeconsole commented Jul 30, 2023

@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.

Grails 6 Installation instructions:

Step 1 - Install the plugin

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.

Step 2 - You are done. Enjoy Bonus features

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'
    }
}

@rainboyan
Copy link
Contributor

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.

@rainboyan
Copy link
Contributor

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

@codeconsole
Copy link
Contributor Author

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.

@rainboyan
Copy link
Contributor

@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?

@codeconsole
Copy link
Contributor Author

@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 grails/grails-gsp#364 so that it does not depend on the SiteMesh 2 libraries to be installed.

@rainboyan
Copy link
Contributor

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

@codeconsole
Copy link
Contributor Author

codeconsole commented Aug 11, 2023

@rainboyan thanks, now that, I'll probably officially 2.5.0 release it within the next week.

@codeconsole
Copy link
Contributor Author

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.

@rainboyan
Copy link
Contributor

@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.

@codeconsole
Copy link
Contributor Author

@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?

@codeconsole
Copy link
Contributor Author

@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).

@puneetbehl
Copy link
Contributor

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?

@codeconsole
Copy link
Contributor Author

yeah, that's correct. Your email got overlooked. I just replied.

@puneetbehl
Copy link
Contributor

@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.

@codeconsole
Copy link
Contributor Author

@puneetbehl ok, I will look into this.

@codeconsole
Copy link
Contributor Author

@codeconsole
Copy link
Contributor Author

Pull Request for core: #13492

Demo running off of 7.0.x:
https://github.com/codeconsole/grails-sitemesh3-demo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants