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

Restore support for Freemarker request parameters and taglibs now that it supports Jakarta #30186

Closed
anabright opened this issue Mar 24, 2023 · 17 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Milestone

Comments

@anabright
Copy link

I just upgraded my app to Spring Boot 3.0.5 (and consequently Spring 6.0.7) and there seems to be something broken with spring-boot-starter-freemarker.

In my Freemarker template, I have this line that used to work before the upgrade:

<div>${RequestParameters.myParam!}</div>

After the upgrade, I get this error when loading the template:

freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:
==> RequestParameters  [in template "template.ftlh" at line 136, column 11]

----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: ${RequestParameters.myParam!}  [in template "template.ftlh" at line 136, column 9]

It seems like RequestParameters is not available anymore.

I originally posted this issue in the spring-boot repo and @wilkinsona kindly pointed out that due to d84ca2b, there's no longer a RequestParameters entry in the model.

Are there plans to fix this?

Thanks!

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 24, 2023
@sbrannen sbrannen added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Mar 24, 2023
@sbrannen sbrannen changed the title Invalid reference to RequestParameters in Freemarker after upgrade Invalid reference to RequestParameters in FreeMarker template after upgrade to Spring Framework 6 Mar 24, 2023
@damir78
Copy link

damir78 commented Apr 1, 2023

Hello @anabright ,
Thank you.
I created an issue: #34637 but unfortunately it was closed.
The implementation of "RequestParameters" is https://github.com/apache/freemarker/blob/v2.3.32/src/main/java/freemarker/ext/servlet/HttpRequestHashModel.java and uses javax.* (for example javax.servlet) instead jakarta.* ( for example jakarta.servlet).

@Paul-Gerarts
Copy link

Paul-Gerarts commented Apr 21, 2023

yes, I upgraded to SpringBoot 3.0.2 as parent and Freemarker had a hash for RequestParameters which doesn't exist anymore.

From the Freemarker docs:
"FreemarkerServlet also puts 3 hashes into the data-model, by which you can access the attributes of the 3 objects directly. The hash variables are: Request, Session, Application (corresponds to ServletContext). It also exposes another hash named RequestParameters that provides access to the parameters of the HTTP request."

Those RequestParameters could be accessed directly in your template, for example:
<input name="myParam" type="hidden" value="${RequestParameters.myParam!}"/>

As I'm working in a legacy project from waaaay back, I was hoping to find a more elegant way rather than getting the parameter from the servletRequest and adding it as an attribute to my model.

@mrhcongc
Copy link

mrhcongc commented May 4, 2023

I see that the issue is more than just not supporting the jakarta.*
The code in the FreeMarkerView.buildTemplateModel has been changed and has removed all the model additions.
I created my own implementations of a few classes to allow me to add the RequestParameters and Request back into the model.
If fixed in a future release, I'll just remove my classes.

@startjava
Copy link

use spring-boot 3.1.2

use url:
http://localhost:8080/test20?selectedValue=d

template code:
<#if listString?? && listString?size!=0> <#list listString as list> <#if RequestParameters['selectedValue']==list> ${list} </#if> <#if RequestParameters['selectedValue']!=list> ${list} </#if> </#list> </#if>

controller code:
@RequestMapping("test20")
public String test20(Model model,HttpServletRequest request,HttpServletResponse response)

{ List listString=new ArrayList(); listString.add("a"); listString.add("b"); listString.add("c"); listString.add("d"); listString.add("e"); request.setAttribute("listString",listString); return "test20"; }

run result :
freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:
==> RequestParameters [in template "test20.ftlh" at line 12, column 12]

Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??

FTL stack trace ("~" means nesting-related):

  • Failed at: #if RequestParameters.selectedValue =...

[in template "test20.ftlh" at line 12, column 7]

same question!


@anabright @mrhcongc @damir78 @Paul-Gerarts

@startjava

This comment has been minimized.

@startjava

This comment has been minimized.

@snicoll
Copy link
Member

snicoll commented Dec 27, 2023

@anabright unfortunately, there's nothing we can do here. Even the latest version of Freemarker does not use Jakarta as far as I can tell.

If you need to use the Servlet integration of Freemarker, only a change in freemarker can help here.

@snicoll snicoll closed this as not planned Won't fix, can't repro, duplicate, stale Dec 27, 2023
@snicoll snicoll added for: external-project Needs a fix in external project and removed status: waiting-for-triage An issue we've not yet triaged or decided on in: web Issues in web modules (web, webmvc, webflux, websocket) labels Dec 27, 2023
@doctore
Copy link

doctore commented May 1, 2024

I had this problem upgrading an old project from Spring 3 to Spring 6, by now we have no time to replace the technology used to render the views, so my solution was adding it as a new model attribute of FreeMarker.

Replacing:

<#if RequestParameters['authfail']??>
  ...
</#if>

By, in backend:

@ModelAttribute("rawRequestParameters") 
public String getRequestParameters(HttpServletRequest request) {
  return ofNullable(request)
            .map(HttpServletRequest::getQueryString)
            .orElse("");
}

and in frontend:

<#if rawRequestParameters?? && rawRequestParameters == "authfail">
  ...
</#if>

@anabright
Copy link
Author

anabright commented May 1, 2024

@anabright unfortunately, there's nothing we can do here. Even the latest version of Freemarker does not use Jakarta as far as I can tell.

If you need to use the Servlet integration of Freemarker, only a change in freemarker can help here.

There's supposed to be a Freemarker release soon that supports jakarta. @snicoll maybe when it's out Spring can be updated to use the new version and add back the missing model attributes like RequestParameters?

@snicoll
Copy link
Member

snicoll commented May 2, 2024

@anabright it's not really actionable right now so please ping again when it's actually available and we'll have a look.

@FloTrEu
Copy link

FloTrEu commented Jul 2, 2024

@snicoll According to apache/freemarker#94 (comment)

You have to use freemarker.ext.jakarta.servlet package instead of freemarker.ext.servlet package, and freemarker.ext.jakarta.jsp instead of freemarker.ext.jsp, everywhere in your application. It's not enough to just update your FreeMarker dependency. We support both pre-Jakarata and Jakarta environments in the same artifact, so the name of the non-Jakarta classes did not change.

I've checked version 2.3.33 and it includes freemarker.ext.jakarta.servlet package.
Could you please give it a try?

@bclozel
Copy link
Member

bclozel commented Jul 2, 2024

It looks like Freemarker 2.3.33 was released in May 2024. Spring Framework 6 was released in November 2022.

We could reintroduce this support in Spring Framework 6.2 at the earliest, so two entire minor versions into the 6th generation. Because we didn't get a lot of requests for this in the meantime, I'm reopening this enhancement request and adding it to our backlog. We'll prioritize this according to community demand.

@bclozel bclozel reopened this Jul 2, 2024
@bclozel bclozel added in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement and removed for: external-project Needs a fix in external project labels Jul 2, 2024
@bclozel bclozel added this to the 6.x Backlog milestone Jul 2, 2024
@snicoll snicoll changed the title Invalid reference to RequestParameters in FreeMarker template after upgrade to Spring Framework 6 Restore Freemarker support now that it supports Jakarta Jul 2, 2024
@snicoll snicoll self-assigned this Jul 18, 2024
@snicoll
Copy link
Member

snicoll commented Jul 18, 2024

@anabright and others interested by this, this should be available shortly in 6.2.0-SNAPSHOT and in the next milestone coming in August. Please give that a try and let us know if you experience a problem.

@anabright
Copy link
Author

@snicoll thanks for the nudge, unfortunately we migrated our freemarker templates to thymeleaf so we could upgrade our project to Spring Boot 3 and it's not in our plans to revert the changes.

@snicoll snicoll modified the milestones: 6.x Backlog, 6.2.0-M7 Jul 19, 2024
@yusuhua
Copy link

yusuhua commented Jul 26, 2024

I tried freemarker 2.3.33, unfortunately the RequestParameters in the .ftl file still point to the freemarker.ext.servlet.* path instead of the freemarker.ext.jakarta.servlet.* path, how should I modify it?

@bclozel
Copy link
Member

bclozel commented Jul 26, 2024

@yusuhua I can't find any reference to "freemarker.ext.servlet" in our codebase. If you're requesting assistance for your application, please do so on StackOverflow. If you believe you've found a bug in Spring Framework, please create a new issue with a minimal application that reproduces the problem.

@snicoll snicoll changed the title Restore Freemarker support now that it supports Jakarta Restore support for Freemarker request parameters and taglibs now that it supports Jakarta Aug 1, 2024
@anabright
Copy link
Author

If anyone still encounters this issue, the workaround is to have a custom FreeMarkerView and manually add RequestParameters to the model:

public class CustomFreeMarkerView extends FreeMarkerView {
  @Override
  protected SimpleHash buildTemplateModel(Map<String, Object> model, HttpServletRequest request,
      HttpServletResponse response) {
    final SimpleHash fmModel = super.buildTemplateModel(model, request, response);
    fmModel.put(FreemarkerServlet.KEY_REQUEST_PARAMETERS, new HttpRequestParametersHashModel(request));
    return fmModel;
  }
}

(Don't forget to register it as a bean)

In a similar vein, since the upgrade to Spring 6 and Freemarker 2.3.33, session attributes added like this
request.getSession().setAttribute("hello", "world") are no longer accesible from a Freemarker template in this way ${hello}.

This is the workaround:

  @Bean
  public CustomFreeMarkerViewResolver viewResolver() {
    CustomFreeMarkerViewResolver viewResolver = new CustomFreeMarkerViewResolver();
    ...
    viewResolver.setExposeSessionAttributes(true);
    return viewResolver;
  }

Hope that helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests