jsp include (or something similar)

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

jsp include (or something similar)

emilime
Hello,

is there any way to include a jsp fragment into a thymeleaf template? it would be a nice way to reuse some custom tags we already have for pagination and some other stuff.

Reply | Threaded
Open this post in threaded view
|

Re: jsp include (or something similar)

Zemi
Administrator
Unfortunately, there is no way to mix JSP and Thymeleaf code, because they follow different paradigms.

JSP code compiles to Java bytecode, while Thymeleaf is based on XML processing.

I can't figure out how this could be achieved, maybe Daniel could share some ideas about this.

On the other side, as Thymeleaf is an emerging technology, we could create and share some processor sets providing basic utilities.
Reply | Threaded
Open this post in threaded view
|

Re: jsp include (or something similar)

Jamie
Setting aside the issue of whether or not this is a good idea :

1) create a custom attribute processor (extending AbstractUnescapedTextChildModifierAttrProcessor?)
that could handle something like <div th:jsp="/foo/bar/baz.jsp">jsp content goes here</div>

2) make sure the HttpServletRequest and HttpServletResponse are available to the attribute processor (put them in the context)

3) create a class that wraps HttpServletResponse and have all the methods 'pass through' except
getWriter() which should return a PrintWriter that is backed by a CharArrayBuffer.  You'll also need a
method that returns you the contents of the buffer.  Wrap the HttpServletResponse with an instance of
this class, so that when the jsp content is written to the response it is actually being written to a buffer.
Thymeleaf writes out the whole result of its template right at the end - if you don't capture the jsp
output it will be written out before any of the thymeleaf content.

4) do a normal request.getRequestDispatcher(jspName).include(request, wrappedResponse)

5) return the content of the HttpServletResponse buffer.

You'd need to be very careful with your HttpServletResponse wrapper class otherwise you might get odd
behaviour in some cases (e.g. with WebSphere dynacache for example - or other things that muck about
with the HttpServletResponse as much as you)


Jamie
Reply | Threaded
Open this post in threaded view
|

Re: jsp include (or something similar)

danielfernandez
Administrator
In reply to this post by emilime
Hi,

There is no way to execute a fragment of JSP from Thymeleaf, because they are different technologies and Thymeleaf does not understand JSP's syntax and language (in the same way the JSP engine does not understand Thymeleaf's).

But you can insert *the result* of executing a JSP page as a fragment in a Thymeleaf template.

How? I'll explain:

Let's imagine your JSP gets executed at the URL http://myapp/doSomethingWithJsp.do

Now add a UrlTemplateResolver to your Thymeleaf configuration, setting viewNames="*.do"  and prefix="http://myapp/".

Finally, in your Thymeleaf template, insert a fragment using an XPath expression instead of a fragment name. This allows you to insert non-thymeleaf fragments into your Thymeleaf templates. XPath expressions are expressed between square brackets:

<div th:include="doSomethingWithJsp.do :: [//div/p]">...

Of course, this method will not only work with JSPs, but also with any other web technology, from PHP to ASP.net, as far as you can apply an XPath expression on it.

Regards,
Daniel.


Reply | Threaded
Open this post in threaded view
|

Re: jsp include (or something similar)

Zemi
Administrator
You both are right, it is possible to create a Thymeleaf Processor to include some external content in the style of the c:import JSTL tag:
   <c:import url="..." />

But the original question was asking about a way "to reuse some custom tags we already have for pagination" and I think this is not possible because Thymeleaf and JSP should share some state objects, or at least it would be very tricky and difficult.

In my opinion, it better to build a solution from scratch for these utilities. Emilime, about pagination, you could be interested this post:
   http://forum.thymeleaf.org/Thymeleaf-and-Pagination-td3258442.html

Reply | Threaded
Open this post in threaded view
|

Re: jsp include (or something similar)

emilime
Yes Zemi, you are perfectly right, solution proposed by Daniel does not fit our intention to reuse a pagination tag.

I've already read the thread about navigation but with that solutions (except ajax jqgrid) I'll obtain something like:

prev | current | next

I need something more complex like the output of displaytag... I think this kind of utilities would be very useful
Reply | Threaded
Open this post in threaded view
|

Re: jsp include (or something similar)

Zemi
Administrator
> with that solutions I'll obtain something like prev | current | next

Take a deeper look a Spring PagedListHolder API, you have methods for almost anything you want, for example page count, number of results, first element on page...

I'm using this approach and it works O.K.
 

Reply | Threaded
Open this post in threaded view
|

Re: jsp include (or something similar)

emilime
so, have you defined a fragment in thymeleaf, based on pagedlistholder, that you reuse in every page you need pagination?
Reply | Threaded
Open this post in threaded view
|

Re: jsp include (or something similar)

Zemi
Administrator
I really use an Attribute Proccesor, but a th:fragment is perfectly OK.

You could achieve this "passing variables" to the fragment, like:

            <div th:with="items=${products},url='productSearch.html'">
                <div th:include="includes.html::pagination"></div>
            </div>

            <div th:with="items=${images},url='imageSearch.html'">
                <div th:include="includes.html::pagination"></div>
            </div>

and using this variables inside the fragment

           <div th:fragment="pagination">
                  < a th:if="${!items.firstPage}"
                         th:href="@{/__${url}__(keyword=${param.keyword}, page=${items.page - 1})}">Previous< /a>
                  < span th:text="${items.page + 1}">1 / 10< /span>
                  < a th:if="${!items.lastPage}"
                        th:href="@{/__${url}__(keyword=${param.keyword}, page=${items.page + 1})}">Next< /a>
            </div>

I know this is a bit too tricky, so I use an Attribute Proccesor to do it using Java code.