Wicket 1.5 和 JSP/servlet 包装

发布于 2025-01-04 23:20:21 字数 3966 浏览 1 评论 0原文

在我正在进行的项目中,我们希望从 Wicket 1.4 升级到 1.5。经过一些工作后,我们大部分工作都正常。

然而,有一件重要的事情还没有发挥作用。需要将旧的 JSP/servlet 包装到新的基于 Wicket 的应用程序中,而旧的 1.4 方法不再起作用。

1.4 中简化的 html 输出

<body>
    <div id="container">
        wrappedContentFromJsp
    </div>  
<body>

1.5 中简化的 html 输出

<body>
    wrappedContentFromJsp   
    <div id="container">        
    </div>  
<body>

因此,所有 JSP 内容都呈现在我们希望将其包装在其中的标记之外

包装魔法发生在我们的内部 AbstractServletWrapperPanelWebMarkupContainer.onRender(MarkupStream markupStream) 重写中。但是,在 Wicket 1.5 中,我们无法调用 markupStream.next(),因为它不再提供。我还没有找到解决这个问题的方法。

1.4 的工作代码,并以示例面板实现作为参考:

public abstract class AbstractServletWrapperPanel extends Panel {

    public AbstractServletWrapperPanel(String id, final  String servletName, String tagId) {
        super(id);
        add(new WebMarkupContainer(tagId) {

            @Override
            protected void onRender(MarkupStream markupStream) {
                markupStream.next();
                try {
                    WebRequestCycle cycle = (WebRequestCycle) RequestCycle.get();
                    ServletRequest request = cycle.getWebRequest().getHttpServletRequest();
                    ServletResponse response = cycle.getWebResponse().getHttpServletResponse();
                    ServletContext context = ((WebApplication) Application.get()).getServletContext();
                    RequestDispatcher rd = context.getNamedDispatcher(servletName);
                    if (rd != null) {
                        rd.include(request, response);
                    } else {
                        // handling...
                    }
                } catch (Exception e) {
                    // handling...
                }
            }
        });
    }
}

//Impl
public class WrapperPanel extends AbstractServletWrapperPanel {
    private static final long serialVersionUID = 1L;

    public WrapperPanel(String id, final String servletName) {
        super(id, servletName, "wrappedContentId");
    }   
}

//WrapperPanel html
<body>
    <wicket:panel>
        <wicket:container wicket:id="wrappedContentId"/>
    </wicket:panel>
</body>

在 1.5 版本中,我通过 (HttpServletRequest)RequestCycle.get().getRequest().getContainerRequest() 和 < code>(HttpServletResponse)RequestCycle.get().getResponse().getContainerResponse()

然后我尝试:

  • 使用 onRender()-magic 而无需1.5 中不再提供的 markupStream.next()
  • 将其移至 onComponentTagBody(MarkupStream markupStream, ComponentTag tag)
    • 注意:要调用 onComponentTagBody(),我必须打开 wicket:container 标签。我还尝试不调用 markupStream.next() ,因为该步骤是在调用 onComponentTagBody 之前在 Component.internalRenderComponent() 中执行的。
  • 将其移动到上面结合的 onComponentTag(ComponentTag tag)
  • 并在 WebMarkupContatiner.onInitialize() 中设置 setRenderBodyOnly(true)
  • 使用 < ;div> 标签代替 wicket:container
  • 使用调试模式来跟踪 1.5 的渲染过程。但我仍然认为我错过了新的 1.5 渲染组件方式的一些关键部分。

由于短期内无法将所有 JSP 功能迁移到 Wicket,因此目前这对我们来说是一个阻碍。

作为参考,1.4 的方法与我在文章 jsp-and-wicket-sitting-in-a-treeWicket wiki

任何解决此问题的帮助将不胜感激!

[编辑]
根据 TheStijn 的建议,我还尝试从 onRender() 调用 getAssociatedMarkupStream(),但这会引发以下错误:org.apache.wicket.markup。 MarkupNotFoundException:未找到组件“... AbstractServletWrapperPanel$1”的“html”类型标记。

In the project I'm on we want to upgrade from Wicket 1.4 to 1.5. After some work we got most things working OK.

However one major thing is not working yet. There's a need to wrap old JSP/servlets into the new Wicket based application and the old 1.4-approach is not working anymore.

Simplified html output in 1.4

<body>
    <div id="container">
        wrappedContentFromJsp
    </div>  
<body>

Simplified html output in 1.5

<body>
    wrappedContentFromJsp   
    <div id="container">        
    </div>  
<body>

So, all the JSP content renders outside the tag that we like to wrap it in.

The wrapping magic happens in our internal AbstractServletWrapperPanel and the WebMarkupContainer.onRender(MarkupStream markupStream) override. However, in Wicket 1.5 we can't invoke markupStream.next() since it's no longer provided. I have not found a way around this yet.

Working code for 1.4 with a sample panel implementation as reference:

public abstract class AbstractServletWrapperPanel extends Panel {

    public AbstractServletWrapperPanel(String id, final  String servletName, String tagId) {
        super(id);
        add(new WebMarkupContainer(tagId) {

            @Override
            protected void onRender(MarkupStream markupStream) {
                markupStream.next();
                try {
                    WebRequestCycle cycle = (WebRequestCycle) RequestCycle.get();
                    ServletRequest request = cycle.getWebRequest().getHttpServletRequest();
                    ServletResponse response = cycle.getWebResponse().getHttpServletResponse();
                    ServletContext context = ((WebApplication) Application.get()).getServletContext();
                    RequestDispatcher rd = context.getNamedDispatcher(servletName);
                    if (rd != null) {
                        rd.include(request, response);
                    } else {
                        // handling...
                    }
                } catch (Exception e) {
                    // handling...
                }
            }
        });
    }
}

//Impl
public class WrapperPanel extends AbstractServletWrapperPanel {
    private static final long serialVersionUID = 1L;

    public WrapperPanel(String id, final String servletName) {
        super(id, servletName, "wrappedContentId");
    }   
}

//WrapperPanel html
<body>
    <wicket:panel>
        <wicket:container wicket:id="wrappedContentId"/>
    </wicket:panel>
</body>

In the 1.5 version I'm getting the request and response via (HttpServletRequest)RequestCycle.get().getRequest().getContainerRequest() and (HttpServletResponse)RequestCycle.get().getResponse().getContainerResponse()

Then I've tried to:

  • use the onRender()-magic without markupStream.next() that's no longer provided in 1.5
  • move it to onComponentTagBody(MarkupStream markupStream, ComponentTag tag)
    • Note: To invoke onComponentTagBody() I had to open up the wicket:container tag <wicket:container wicket:id="wrappedContentId"></wicket:container>. I also tried without invoking markupStream.next() as that step is performed in Component.internalRenderComponent() just before onComponentTagBody is invoked at all.
  • move it to onComponentTag(ComponentTag tag)
  • combined above with setting setRenderBodyOnly(true) in the WebMarkupContatiner.onInitialize()
  • use a <div> tag instead of a wicket:container
  • use debug mode to track down the rendering process of 1.5. But still, I guess I'm missing out some key part of the new 1.5 way of rendering components.

Since it's not an option to migrate all that JSP functionality to Wicket anytime soon this is kind of a showstopper for us at the moment.

For reference, the 1.4 way of doing this is much similar to the approach I found in the article jsp-and-wicket-sitting-in-a-tree and on the Wicket wiki

Any help solving this issue would be very appreciated!

[EDIT]
After a suggestion from TheStijn I've also tried invoking getAssociatedMarkupStream() from onRender() but that raises the following error: org.apache.wicket.markup.MarkupNotFoundException: Markup of type 'html' for component '... AbstractServletWrapperPanel$1' not found.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

猫烠⑼条掵仅有一顆心 2025-01-11 23:20:21

以前没有使用过这个,但(Web)MarkupContainer有一个方法getAssociatedMarkupStream,它返回MarkupStream,这应该适合你。

1.5 迁移指南中提到了这一点,但不是很好:

同一主题:onRender(MarkupStream) 已更改为
onRender();不再有标记流。每个组件您都可以获得一次
您通过 getMarkupStream() 调用了 render()。

https://cwiki.apache.org/WICKET /migration-to-wicket-15.html#MigrationtoWicket1.5-Componentrendering

Not used this before but (Web)MarkupContainer has a method getAssociatedMarkupStream which returns the MarkupStream, this should work for you.

It is mentioned in the 1.5 migration guide but not very well:

On the same topic: onRender(MarkupStream) has been changed to
onRender(); no more MarkupStream. You can get for every component once
you called render() via getMarkupStream().

https://cwiki.apache.org/WICKET/migration-to-wicket-15.html#MigrationtoWicket1.5-Componentrendering

凝望流年 2025-01-11 23:20:21

在马丁·格里戈罗夫的大力帮助和指导下,我找到了解决方案。要了解到达那里的过程,请查看 用户论坛

请注意,以下只是尝试使其正常工作的原始输出,可能有一些更好的“打包”方法 它。所以就接受它的本来面目吧。

//Stripped code for clarity

@Override
public void onComponentTagBody(MarkupStream markupStream, ComponentTag tag) {

 //Set up mock response and dispatch.   
 ServletContext context = WebApplication.get().getServletContext(); 
 ServletRequest request = (HttpServletRequest)RequestCycle.get().getRequest().getContainerRequest();
 MockResponse mockResponse = new MockResponse((HttpServletResponse)RequestCycle.get().getResponse().getContainerResponse());
 RequestDispatcher rd = context.getNamedDispatcher(aServletName);
 rd.include(request, mockResponse);

 //As in Wicket's Include.onComponentTagBody(MarkupStream markupStream, ComponentTag tag)
 replaceComponentTagBody(markupStream, tag, mockResponse.getOutput());
}


private static class MockResponse extends HttpServletResponseWrapper {    
 ServletOutputStream servletStream;
 ByteArrayOutputStream byteStream;

 public MockResponse(HttpServletResponse response) {
  super(response);      
  byteStream = new ByteArrayOutputStream();
  servletStream = new ServletOutputStream() {

    @Override
    public void write(int b) {
       byteStream.write(b);
     }
   };
 }

 @Override
 public ServletOutputStream getOutputStream() {
  return servletStream;
 }

 public String getOutput() {
    //NOTE: Remember to clean up IO in real usage...
    return byteStream.toString("UTF-8"); //Provide desired encoding
  }  
}

那么为什么我不使用 org.apache.wicket.protocol.http.mockMockHttpServletResponse 来代替呢?
由于某种原因,getWriter()getOutputStream() 都没有被调用,但我稍后可能会进一步研究。

After great help and pointers from Martin Grigorov I found the solution to this. To follow the process of getting there, hava look at the user's forum

Please note that following is just the raw output of trying to get it to work at all, there might be some nicer way to "package" it. So take it for what it is.

//Stripped code for clarity

@Override
public void onComponentTagBody(MarkupStream markupStream, ComponentTag tag) {

 //Set up mock response and dispatch.   
 ServletContext context = WebApplication.get().getServletContext(); 
 ServletRequest request = (HttpServletRequest)RequestCycle.get().getRequest().getContainerRequest();
 MockResponse mockResponse = new MockResponse((HttpServletResponse)RequestCycle.get().getResponse().getContainerResponse());
 RequestDispatcher rd = context.getNamedDispatcher(aServletName);
 rd.include(request, mockResponse);

 //As in Wicket's Include.onComponentTagBody(MarkupStream markupStream, ComponentTag tag)
 replaceComponentTagBody(markupStream, tag, mockResponse.getOutput());
}


private static class MockResponse extends HttpServletResponseWrapper {    
 ServletOutputStream servletStream;
 ByteArrayOutputStream byteStream;

 public MockResponse(HttpServletResponse response) {
  super(response);      
  byteStream = new ByteArrayOutputStream();
  servletStream = new ServletOutputStream() {

    @Override
    public void write(int b) {
       byteStream.write(b);
     }
   };
 }

 @Override
 public ServletOutputStream getOutputStream() {
  return servletStream;
 }

 public String getOutput() {
    //NOTE: Remember to clean up IO in real usage...
    return byteStream.toString("UTF-8"); //Provide desired encoding
  }  
}

So why didn't I use org.apache.wicket.protocol.http.mockMockHttpServletResponse instead?
For some reason neither getWriter() or getOutputStream() got invoked, but I might look further into that later.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文