How can you build an absolute URL in thymeleaf? - java

I would like to display an absolute url generated at run-time with a parameter. Not create a href to a page but display the URL using th:text. Any simple way to do this with Tymeleaf (without having to concatenate the URL pieces from #request object and without using some MVC utility class)?
Attempt 1
<p th:text="#{/myServlet(myParam=${dynamicParameter})}" /> - only displays part of the URL leaving out the protocol, port and host name. I am getting /myServlet?myParam=123. The same behavior as for th:href, if you inspect the <a> you will see the same href - in that case the browser helps by inferring the protocol, port and so on
Attempt 2
th:text="#{__${#httpServletRequest.requestURI}__}" - produces a relative URI of the current page that doesn't include the protocol and so on
Attempt 3
th:text="#{__${#httpServletRequest.requestURL}__}" - produces this time an absolute URL of the current page containing the protocol, host and servlet context. The problem now is when I display this text from a different page, my URL is ...myApp/myOtherServlet so I need to edit this string to replace myOtherServlet with the URI I want.
Non Tymeleaf Attempt 1
#Service("urlUtils")
public class UrlUtilsServiceImpl implements UrlUtilsService {
#Override
public String getAbsoluteUrlTo(final String aPath, final String param, final String value){
return ServletUriComponentsBuilder
.fromCurrentContextPath()
.path(aPath)
.queryParam(param, value)
.build().toString();
}
}
page.html:
th:text="${#urlUtils.getAbsoluteUrlTo('/myServlet', 'myParam', ${dynamicParameter})}"
The problem is the host name that can be aliased before it reaches my server (see this).
Thymeleaf+JS Sollution
Using some java script plus thymeleaf
<p id="myUrl" th:text="#{/myServlet(myParam=${dynamicParameter})}" />
<script type="text/javascript">
$(document).ready(function () {
var myUrl= $("#myUrl");
myUrl.text(window.location.origin + myUrl.text());
});
</script>

You can concatenate servlet request on the fly:
th:text="${#httpServletRequest.scheme}+'://'+${#httpServletRequest.serverName}+':'+${#httpServletRequest.serverPort}+#{/myServlet(myParam=${dynamicParameter})}"
Or for JavaScript:
<script type="text/javascript">
GLOBAL.serverURI = '[[${#httpServletRequest.scheme}+'://'+${#httpServletRequest.serverName}+':'+${#httpServletRequest.serverPort}+#{/myServlet(myParam=${dynamicParameter})}]]';
</script>

Related

How to send list from controller and accept json in jsp

I want to display that list in json format. When I run this code, it does not display any data in json format but gets in other format. How to display that list?
Controller class
#Controller
public class RoomController {
#RequestMapping(method = RequestMethod.GET)
public ModelAndView saveEmployee(){
System.out.println("welcome");
return new ModelAndView("NewFile","message","hello");
}
#RequestMapping(value="ViewMember",method=RequestMethod.GET)
public #ResponseBody List<RoomMembers> getRoomMembers() {
System.out.println("second test");
List<RoomMembers> roomMemberList= new ArrayList<RoomMembers>();
roomMemberList=roomDao.listMember();
return roomMemberList;
}
Jsp file is
<head>
<title>Spring MVC Ajax Demo</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script type="text/javascript">
function doAjax() {
$.ajax({
url: '/RoomController/ViewMember',
type: 'GET',
success: function(data) {
var roommember=JSON.parse(data);;
$('#time').html(roommember);
}
});
}
</script>
</head>
<body>
<button id="demo" onclick="doAjax()" title="Button">Get the time!</button>
<div id="time">
</div>
</body>
It seems you are requesting the wrong url. In the script in your jsp, the url passed do $.ajax() is url /RoomController/ViewMember.html. But in your controller you have mapped ir as simply 'ViewMember'
#RequestMapping(value="ViewMember",method=RequestMethod.GET,headers="Accept=application/json")
Try requesting just /RoomController/ViewMember and let's us know wether it works or not.
EDIT:
You say that .html url gets called and that you are using Spring 4.0.6, and that you get a HTTP 406 (NOTACCEPTABLE) response.
First check if you are sending Accept header as "application/json". But you won't be able to receive an HTTP 200 with json response in a controller mapped with ".html"/".htm" in a Spring MVC Controller with Spring 3.2 or above. From https://stackoverflow.com/a/39479308/4190848:
As of Spring 3.2+, the content negotiation has other facts in account prior to eval Accept header:
From https://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc:
Enabling Content Negotiation in Spring MVC
Spring supports a couple of conventions for selecting the format
required: URL suffixes and/or a URL parameter. These work alongside
the use of Accept headers. As a result, the content-type can be
requested in any of three ways. By default they are checked in this
order:
Add a path extension (suffix) in the URL. So, if the incoming URL is something like http://myserver/myapp/accounts/list.html then HTML
is required. For a spreadsheet the URL should be
http://myserver/myapp/accounts/list.xls. The suffix to media-type
mapping is automatically defined via the JavaBeans Activation
Framework or JAF (so activation.jar must be on the class path).
A URL parameter like this: http://myserver/myapp/accounts/list?format=xls. The name of the
parameter is format by default, but this may be changed. Using a
parameter is disabled by default, but when enabled, it is checked
second.
Finally the Accept HTTP header property is checked. This is how HTTP is > actually defined to work, but, as previously mentioned, it
can
be problematic to use.
That actually means that if you map a #Controller method with a
.htm(l) suffix, it is intended to return html and won't return
json nor any other format even if you sent other format as Accept
header.
...
So change your mapping to other suffix than ".html"/".htm" (or use no suffix) and you will solve your error
the url in ajax is wrong,you should write "ViewMember".

Grails get url of originating controller

I have a URL say abc.com/somecontroller?someparam=1 which renders a form. Form on submit sends the form params to /ajaxAction
Is there a way I could get this abc.com/somecontroller?someparam=1 (i.e. the form URL?)
I am more interested in getting the someparam value from the URL of the form.
PS: the above URL abc.com/somecontroller?someparam=1 is dynamically generated, so I can not access it otherwise.
And request.forwardURI will give me /ajaxAction (i.e. the URL of the action in form and not the url of the form itself).
EDIT:
I have no control over form as it is also dynamic and user has hundreds of templates to select from. Each template has different no. of fields.
So if I would prefer some other way to get the URL.
Why don't you use javascript in form and add to ajax request array with GET params? (or with the url of the action which generated form)
You can get them from original request f.e. by this script.
While rendering the GSP of your form, you can do like this:
myaction.gsp
<html>
<body>
<!-- Your content -->
<script>
var paramsString = '${params.collect { k, v-> "$k=$v" }.join​​​​​​​​​​​​​​​​​​​​​​("&")​​​ }';
</script>
</body>
</html>
So, when you GSP is rendered, the script tag will have something like this (for a URL abc.com/somecontroller?someparam=1&foo=2:
var paramsString = 'someparam=1&foo=2';
Now, in your AJAX code, you can pass that string as the query arguments:
$.ajax({
url: '/ajaxAction?' + paramsString
/* rest of the AJAX code */
});
Now, in your ajax controller action, you can simply do the params.someparam.
EDIT
Well, I just realized that you don't have to any GSP stuff I mentioned above. Simply do the AJAX call like this:
$.ajax({
url: '/ajaxAction' + location.search
/* rest of the AJAX code */
});
The location.search will give you the direct string: ?someparam=1&foo=2
I ended up using flash to store the someparam
In my controller which is being used to render the form at abc.com/somecontroller?someparam=1 I use flash as this:
flash.put("someparam", params.someparam)
This worked as a quick workaround to the issue. I feel this would work well in situations where I have no control over the gsp.
If anyone finds any issue, please comment otherwise I will mark this as the answer.

XSS - encode - decode a href/url

I have a usecase where I have a text input field which takes URL and saves it.
That saved url is used in a jsp file
<script type="text/javascript">
var defaultSimulatorUrl = '<%= defaultSimulatorUrl %>';
</script>
Variable defaultSimulatorUrl is used to show in prefilled text input fields
Some attacker can attack defaultSimulatorUrl's value by sending http://abcxyz.com?a=b&c=d';alert(1);//
Script content will be converted to
<script type="text/javascript">
var defaultSimulatorUrl = 'http://abcxyz.com?a=b&c=d';alert(1);//';
</script>
My problem is if I encode this Url using com.adobe.granite.xss.XSSAPI.encodeForHTML(), how can i get orignal url to show in input field
Or Can I encode it by some other means to be used in prefilled text input fields
XSSAPI does not provides api to decode string back
I used XSSAPI's encodeForJS method which solved my problem

How I do get an image blob from JSP to JavaScript?

I retrieved a blob along with some other data from a table, say name and image:
name = varchar, image = blob
I set this to an object in my filter and pass it to the JSP file:
request.setAttribute("info", object);
In the JSP file I get that data:
request.getAttribute("info");
Now that I have the data from that object how do I go about passing that info to my JS file and render the image as a source for the JS file?
I'm trying:
<div>
<script type="text/javascript" src="jsFile.js></script>
</div>
var name = <%=info.name%>;
var image = <%=info.image%>
It just doesn't seem to be working. What is the correct method of doing this?
This isn't going to work. Leave the blob there in the server side. JavaScript on the client side can't do anything sensible with binary data. All it needs is an URL of the image so that it can reference it in the src attribute of a HTML <img> element, so that the webbrowser can in turn do its job of downloading and displaying the image. Best would be to include the image identifier in the URL. The name is unique for the image, right? Use that in the URL instead.
The first step is to let JS create a HTML <img> element with the proper src attribute which points to an URL which returns the image. Assuming that you're preparing the data like follows
String name = "foo.png";
String imageURL = "imageservlet/" + name;
request.setAttribute("imageURL", imageURL);
and are printing it in JSP(!) as if it are JS variables as follows
<script>
var imageURL = '${imageURL}';
// ...
</script>
(please note that those singlequotes are thus mandatory to represent them as a JS string variable)
so that they end up in the generated HTML source like follows (rightclick page in browser and do View Source to verify it)
<script>
var imageURL = 'imageservlet/foo.png';
// ...
</script>
then you can create the image as follows
var img = document.createElement("img"); // or getElementById("someId")?
img.src = imageURL;
// ... add to document?
(please note that this is just an example, I have no utter idea what the functional requirement is and what you would like to do with this image element, even more, perhaps JS code isn't needed at all for the concrete functional requirement)
so that it ends up like this in HTML:
<img src="imageservlet/foo.png" />
Now, the second step is to create a servlet which listens on an URL pattern of /imageservlet/*, retrieves the image as an InputStream from the database by the passed-in indentifier and writes it to the OutputStream of the response along a set of correct response headers. Long story short, I've posted several answers before as to how to do it, they contains kickoff code snippets:
How to retrieve and display images from a database in a JSP page?
Writing image to servlet response with best performance
You can access your data from the script if you set the variables in a script block before your jsFile.js. Ie:
<div>
<script type="text/javascript">
var name = <%=info.name%>;
var image = <%=info.image%>;
</script>
<script type="text/javascript" src="jsFile.js></script>
</div>
I'm not sure how you intend to handle the binary (BLOB) image data however? Typically this would be written to an image file on the server and referenced via an img tag:
<img src="/path/to/myimage.jpg" />
Instead of passing your blob data to the JSP file, I would suggest having the server (your servlet) pass a URL to the JSP which the browser can use to get the image via an img tag. You can either write the blob data to a URL or write a servlet that writes out Content-type: image/jpeg (or similar) data when passed an id, ie:
<img src="http://www.yourserver.com/GetImage?imageId=xxx" />

Struts2 parameter to javascript

I have a struts2 action with a field: private Long omradeId;
The field has a getter.
The action is sent to a jsp and within that jsp i can access the field using <s:property>tag. Thats all good.
Now i also have within the jsp a section where i define a <script>. Within that script i would like to create a variable that will build a url with the above mentioned struts2 field as a value.
<script type="text/javascript">
var url = "/path/to/action?parameter1=";
</script>
How can i put the value of omradeId after the equals (=) sign? I tried using <s:property>but that did not work.
Any suggestions?
"/path/to" will change depending on the web server. To avoid this use the struts2 url tag.
See: http://struts.apache.org/2.x/docs/url.html
For an action called "action" in namespace "/" with a parameter called parameter1 having the value omradeId, you would simply say:
<s:url namespace="/" action="action">
<param name="parameter1" value="%{omradeId}"/>
</s:url>
putting the above into the JS variable we have:
var url = "<s:url action="action"><param name="parameter1" value="%{omradeId}"/></s:url>";
Using the above will mean your application can be installed on different application servers without change.
Having formated xml is nicer than inline, if using a lot of parameters adding the var parameter to the s:url tag to give it a name and then you can reference this string in a number of places with the s:property tag would keep things clean.
<s:url namespace="/" action="action" var="myString">
<param name="parameter1" value="%{omradeId}"/>
</s:url>
var url = "<s:property value="#myString"/>";
This should work:
<script type="text/javascript">
var url = "/path/to/action?parameter1=<s:property value="omradeId">";
</script>
If not you should check if the value is not null and value is successfully set in your action class.

Categories

Resources