Liferay Freemaker: how to get Request object in template? - liferay

I am using Liferay 6.2 and freemaker for web content templates. I need to get request object in template. When I try to use ${Request.getRequest()} it throws error Expression Request is undefined.
Full code here
<#assign userService=utilLocator.findUtil('my-portlets', org.test.service.UserService')>
<#if userService.isUser(Request.getRequest())>
<h1>is User</h1>
</#if>
My handling method for userService
public Boolean isUser(HttpServletRequest request) {
//some logic
return true;
}
How I can get Request object in freemaket ftl template?

You can just use the request variable like in
<#if request.getParameter("something")??>
I find this file always useful
https://github.com/agmip/liferay-portal-impl/blob/master/src/com/liferay/portal/freemarker/FreeMarkerVariablesImpl.java
Also, the use of $ is probably causing you some issues there, as it is not used as it is in velocity..

FreeMarker variables are case sensitive and don't start with the $ sign (like in velocity).
Use the request variable.

Related

How to use template engine without using any controller in standalone NestJS Application?

I'm trying to create telegram chatbot application using nestjs-telegraf
And then I've idea to use template engine like what has been taught from here, to render the reply message for each message has been received.
But, I don't find any way how to do that. All I have got is everyone using #Res res parameter in their method, and then just return res.render(...)
Is there any way to that?
I don't want to manually format the reply message by using ` and using string interpolation.
I think you can use a callback parameter from res.render(), like this:
import { Response } from 'express';
import { Post, Controller, Res } from '#nestjs/common';
#Controller()
export class MyController {
#Get()
root(#Res() response: Response) {
await response.render(
'index',
{ variable: 'My variable' },
function (error, html) {
console.log(html)
}
);
// return any JSON you want
return response.send({message: 'You HTML was proceed'})
}
}
Choose View Engine
First of all, you have to choose a view engine, this will be in charge of rendering the template and doing the necessary interpolation.
You can check these view engines:
Handlebars: https://handlebarsjs.com/
Pug: https://pugjs.org/api/getting-started.html
Configure the app
Then, you have to create a view and public folders, usually this folder is located in the root layer of your project directory.
Then, add in your main.ts the following code
This will tell express where are the views (templates) and the public (Css or Js files, etc.) files located.
Add the setViewEngine method indicating the view engine, in this case is handlebars (hbs).
Create template files
With this configuration you can start creating your templates files, let's see the example on the docs.
He created a file in the views folder called index.hbs and wrote that code, handlebars is basically html and the curly braces indicates that you can put a value on that space.
Render the file
The last thing to do is on your controller, create a Get method, add the render decorator and put the name of the view file, then return an object containing the values that you want to interpolate on the template and handlebars will do the rest.
If you need more info or have some questions you can leave me a comment :)

trying to use POST, but API tries to use GET

I'm trying to get an api method to use POST but it insists on trying to use GET. I've Googled and searched SO, but everything I try just returns the same message.
Here's my controller:
[Route("api/game/{gameId}/createcharacter/{name}")]
[AcceptVerbs("POST")]
[HttpPost]
public IHttpActionResult PostNewCharacter([FromBody]string name)
{
return Created("created", CharacterGenerationService.CreateNewCharacter(name));
}
Here's the message I get no matter what I try:
message: "The requested resource does not support http method 'GET'."
Request
URL:http://localhost:61645/api/game/452/createcharacter/testChar1
Request Method:GET Status Code:405 Method Not Allowed Remote
Address:[::1]:61645
I am using : using System.Web.Http;
Is there a trick to this?
Thanks
use this code:
[Route("api/game/{gameId}/createcharacter/{name}")]
[HttpPost]
public IHttpActionResult PostNewCharacter(string name)
{
return Created("created", CharacterGenerationService.CreateNewCharacter(name));
}
In the route template you said you will get the name parameter value from the URL but in the signature of your method your decorate that same parameter with FromBody attribute which tell that the value will be retrieved from the message body.
You have two choices :
remove the FromBody attribute and your URL will work correctly
or remove the {name} parameter in your route template and post the name value into your request body.
What about the gameId parameter ?
Don't you need it in your method ? If yes, then you need to pass it as a method parameter.

ASP MVC AttributeRoutes Languagetoken in URL, keep original Url

I'm using attribute routing with asp mvc 5.2.
I want the user to be able to call the urls with a language token like "de" or "en".
mydomain/en/foo
For this I created a routeattribute with a constraint like descriped in this blog post
This works well when the locale part is at the end like:
[LocaleRoute("home/index/{locale}/","de)]
then i could call home/index or home/index/de
But when I move this to the beginning i can't omit the locale any more.
[LocaleRoute("{locale}/home/index","de)]
There i can only call de/home/index but home/index returns a 404 Notfound. Also the constraint isn't called. It looks like the route isn't just found.
Any hints on what i'm doing wrong and what i have to do?
You probably need to specify that the locale is an optional argument :
[LocaleRoute("{locale?}/home/index","de")]
On a side note, are you using different controllers for de & en ? If you use a single controller you don't need LocaleRoute and can use the default attributes (http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx) :
[RouteArea("{locale?}/home/")]
public class HomeController : Controller
{
...
[Route("index")]
public ActionResult Index (string culture)
{
...
}
}
EDIT
You can also register your action with the following additional route as long as you're careful with providing a default value for culture or treating null.
[Route("/home/index")]

Change XSLT of the SearchResultWebPart during the FeatureActivated

I have a piece of code which changes XSLT of a SearchResultWebPart at Sharepoint 2010 Search Center result page (spFileItem - is SPFile of a search result page) :
SPLimitedWebPartManager wpManager = spFileItem.GetLimitedWebPartManager(PersonalizationScope.Shared);
foreach (WebPart wpItem in wpManager.WebParts)
{
if (wpItem is CoreResultsWebPart)
{
((CoreResultsWebPart)wpItem).UseLocationVisualization = false;
((CoreResultsWebPart)wpItem).Xsl = someXSL;
wpManager.SaveChanges(wpItem);
}
spFileItem.Update();
spFileItem.CheckIn(Consts.CheckInComment, SPCheckinType.MajorCheckIn);
But, this code doesn't work if it is called on feature activated (gives InvalidOperationException - incorrect object state). However it perfectly works in Console application.
After some reflecting, I found out that there is a piece of code inside the SearchResultWebPart, which checks if the webpart wasn't initialized - it throws the mentioned above exception on setting XSL property. Does anybody know how to work this problem out? For me it'd be quite convenient to do XSL change at FeatureActivated...
I found a solution to my problem, but it uses different way of setting xsl for SearchResultBaseWebPart.
SPLimitedWebPartManager wpManager = spFileItem.GetLimitedWebPartManager(PersonalizationScope.Shared);
foreach (WebPart wpItem in wpManager.WebParts)
{
if (wpItem is CoreResultsWebPart)
{
((CoreResultsWebPart)wpItem).UseLocationVisualization = false;
((CoreResultsWebPart)wpItem).XslLink = spFileItem.Web.Url + #"/_layouts/XSL/MYXSL.xsl";
wpManager.SaveChanges(wpItem);
}
}
spFileItem.Update();
spFileItem.CheckIn(Consts.CheckInComment, SPCheckinType.MajorCheckIn);
I feel you mix up a few things in the question. You would like to set the Xsl property of the CoreResultsWebPart. This class has no direct implementation of the Xsl method, so it inherits the implementation of its parent class (SearchResultBaseWebPart). The Xsl property setter try to set the XslHash property (but only if we are after the OnInit that sets _BeforeOnInit = false;), and the setter method of the XslHash property throws an InvalidOperationException, but this exception should be catched by the try/catch block in Xsl property setter anyway. I don't see any other potential source of InvalidOperationException in the code.
You should check the patch level of your SP2010 (is it SP1/some of the cummulative updates/original version?) and try to activate the feature from different contexts (from web site / STSADM or PowerShell).
But first I suggest you to add a try / catch block to your feature receiver code and trace out the error details (like stack trace) and monitor the results using DebugView.

parameter in URL jsf2

I need to have this link:
http://myserver:/myproject/innerpage/clip.jsf&id=9099
to extract the id from a code like this:
HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
String clipId = request.getParameter("id");
When I run it on tomcat I get:
message
/OnAir/innerpage/clip.jsf&id=9099
description The requested resource
(/OnAir/innerpage/clip.jsf&id=9099)
is not available.
When I run it without &id=9099 it runs all right.
How can I make it run?
The separator character between path and query string in URL is ?, not &. The & is separator character for multiple parameters in query string, e.g. name1=value1&name2=value2&name3=value3. If you omit the ?, then the query string will be seen as part of path in URL, which will lead to a HTTP 404 page/resource not found error as you encountered.
So, this link should work http://myserver:port/myproject/innerpage/clip.jsf?id=9099
That said, there's a much better way to access the request parameter. Set it as a managed property with a value of #{param.id}.
public class Bean {
#ManagedProperty(value="#{param.id}")
private Long id;
#PostConstruct
public void init() {
System.out.println(id); // 9099 as in your example.
}
// ...
}
The EL #{param.id} returns you the value of request.getParameter("id").
A tip: whenever you need to haul the "raw" Servlet API from under the JSF hoods inside a managed bean, always ask yourself (or here at SO): "Isn't there a JSF-ish way?". Big chance you're unnecessarily overcomplicating things ;)
You first have to show us how you are sending the parameter in your JSF, is it a commandButton/Link? An outputLink? A ? Also are you using redirect=true?
Chances are you are losing the id somewhere during the request.

Resources