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

[#233] Reactivating the Thymeleaf extension #291

Merged
merged 1 commit into from
Feb 23, 2022

Conversation

jelemux
Copy link
Contributor

@jelemux jelemux commented Jan 19, 2022

This reenables the Thymeleaf extension by using its 3.1.0.M1 milestone release (which uses the jakarta namespace).

To adapt to changes in Thymeleaf, CDIWebContext had to be changed to use the jakarta namespace and the new IWebExchange. Since JakartaServletWebApplication has been established to wrap ServletContext in Thymeleaf, there needed to be a producer to inject it into both DefaultTemplateEngineProducer and ThymeleafViewEngine. But because JakartaServletWebApplication is a final class, a wrapper for it had to be written in order to use CDI.

Fixes #233

@jelemux jelemux changed the title Tried reactivating the Thymeleaf extension but ran into problems [#233] Tried reactivating the Thymeleaf extension but ran into problems Jan 19, 2022
@chkal
Copy link
Contributor

chkal commented Jan 23, 2022

I'm currently creating two instances of JakartaServletWebApplication (for DefaultTemplateEngineProducer and ThymeleafViewEngine respectively) which is not pretty, but it should not be the problem here.

Maybe we could simply "produce" an application-scoped instance of JakartaServletWebApplication and use it in both classes? Not sure if this works, as I didn't have a detailed look at the code yet.

The problem is that somehow the request from the ViewEngineContext has a ServletContext different from the one injected into the ViewEngine and Thymeleaf doesn't like that at all.

It is just a guess, but if we use @Inject ServletContext, we will most likely get a CDI proxy class instead of the real ServletContext instance. I guess there are a few ways to get a reference to the context:

// (A) Directly inject via CDI, but I guess you will get a wrapper
@Inject 
private ServletContext servletContext;

// (B) Inject the request and then call request.getServletContext(). Should return the "real" servlet context?
@Inject 
private HttpServletRequest request;

// (C) Like (B) but Krazo spezific and will return the same request as @Context HttpServletRequest
@Inject 
@JaxRsContext
private HttpServletRequest request;

// (D) via ViewEngineContext.
viewEngineContext.getRequest(HttpServletRequest.class).getServletContext()

To make things more complicated: HttpServletRequests can be wrapped via servlet filter. We actually even have some special handling in Krazo to "unwrap" these wrappers. The result is what you will get from ViewEngineContext. See:

HttpServletRequest request = unwrapOriginalRequest(injectedRequest);
HttpServletResponse response = unwrapOriginalResponse(injectedResponse);

Maybe I'll find some time tomorrow to have a look at your branch.

@jelemux
Copy link
Contributor Author

jelemux commented Jan 23, 2022

Maybe we could simply "produce" an application-scoped instance of JakartaServletWebApplication and use it in both classes? Not sure if this works, as I didn't have a detailed look at the code yet.

JakartaServletWebApplication is a final class so it cannot be proxied by CDI.
To solve this, I see three possibilities:

  1. Create a wrapper object for JakartaServletWebApplication and produce that.
  2. Create an issue/PR with Thymeleaf asking them to remove the final modifier.
  3. Create an issue/PR with Thymeleaf including the buildExchange() method (which we need) in IServletWebApplication. That way we could just produce and inject that.
    (This would add the need for a wrapper around HttpServletRequest and HttpServletResponse in Thymeleaf.)

It is just a guess, but if we use @Inject ServletContext, we will most likely get a CDI proxy class instead of the real ServletContext instance.

Thanks, that seems to be the case. My current (local) codebase uses option D and that works.

@jelemux
Copy link
Contributor Author

jelemux commented Jan 23, 2022

I now have it in a working state and pushed the changes. Have a look and tell me what you think.

@jelemux jelemux changed the title [#233] Tried reactivating the Thymeleaf extension but ran into problems [#233] Reactivating the Thymeleaf extension Jan 23, 2022
@jelemux
Copy link
Contributor Author

jelemux commented Jan 31, 2022

I don't like my current solution at all.
I'll try solution 3:

  1. Create an issue/PR with Thymeleaf including the buildExchange() method (which we need) in IServletWebApplication.

@erdlet
Copy link
Member

erdlet commented Feb 5, 2022

@chkal after a look into the PR I'm afraid we need a CQ because of the minor update, right? Do you know if we need one for the final 3.1.0 again after creating one for 3.1.0.M1?

@erdlet
Copy link
Member

erdlet commented Feb 5, 2022

I don't like my current solution at all. I'll try solution 3:

  1. Create an issue/PR with Thymeleaf including the buildExchange() method (which we need) in IServletWebApplication.

Good idea, thanks for doing that 🍻

@jelemux jelemux marked this pull request as ready for review February 18, 2022 07:43
@jelemux
Copy link
Contributor Author

jelemux commented Feb 18, 2022

As we agreed yesterday in the MVC Spec Meeting: Since there is no reaction from Thymeleaf maintainers to my PR, we'll just merge this current solution.

The only open point is the CQ that @erdlet pointed out.

@chkal after a look into the PR I'm afraid we need a CQ because of the minor update, right? Do you know if we need one for the final 3.1.0 again after creating one for 3.1.0.M1?

@jelemux jelemux requested a review from erdlet February 18, 2022 07:49
Copy link
Contributor

@chkal chkal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @jelemux. Sorry for the super long delay. I finally found some time to review your changes.

Overall, it looks great. I just added a few comments, but I would also be fine with merging the current state of the PR. Feel free to have a look at my comments. :-)

ext/pom.xml Outdated Show resolved Hide resolved
private HttpServletRequest request;

@Produces
@ApplicationScoped
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should add the @Internal qualifier here? We use this qualifier for some beans used internally by Krazo to protect ourselves against potential conflicts with other libraries which produce the same type as well. We use it for HttpServletRequest for example.

I'm not super sure if we should do it here as well. I just wanted to mention it. :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to understand what the @Internal qualifier does but I don't know if I fully get it yet.
If using it means that the user cannot provide their own producer to override ours, then I would refrain from using it because it might be useful for the user to configure JakartaServletWebApplication themselves.

Also if you were afraid that the user might want to inject a JakartaServletWebApplicationWrapper somewhere in their code using their own producer: I don't think that this should happen as JakartaServletWebApplicationWrapper was written by us specifically for the purpose we are using it for and nothing else.

I hope that clarified things and that I correctly understood what @Internal does.

…es in Thymeleaf

This reenables the Thymeleaf extension by using its 3.1.0.M1 milestone release (which uses the jakarta namespace).
To adapt to changes in Thymeleaf, CDIWebContext had to be changed to use the jakarta namespace and the new IWebExchange.
Since `JakartaServletWebApplication` has been established to wrap ServletContext in Thymeleaf, there needed to be a producer to inject it into both `DefaultTemplateEngineProducer` and `ThymeleafViewEngine`.
But because `JakartaServletWebApplication` is a final class, a wrapper for it had to be written in order to use CDI.
@erdlet
Copy link
Member

erdlet commented Feb 21, 2022

CQ https://dev.eclipse.org/ipzilla/show_bug.cgi?id=23960 created.

@erdlet erdlet added the CQ required CQ required before merging label Feb 21, 2022
@erdlet
Copy link
Member

erdlet commented Feb 22, 2022

CQ is approved, so we can finally merge this PR :)

@jelemux please let me known if you want to squash something before merge or if everything is fine for you.

@erdlet erdlet removed the CQ required CQ required before merging label Feb 22, 2022
@jelemux
Copy link
Contributor Author

jelemux commented Feb 22, 2022

I already squashed everything, so should be good to go for the merge

@erdlet erdlet merged commit 9afb5aa into eclipse-ee4j:master Feb 23, 2022
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

Successfully merging this pull request may close these issues.

Reactivate the Thymeleaf extension
3 participants