I need to change the FreeMarker behavior about processing template&data in case some data are missing.
In missing case I need to let the template unchanged and continue in processing.
Example:
Template:
...
var1 = ${var1}
var2 = ${var2}
...
Data:
var1 = Hello
I need Result after processing:
...
var1 = Hello
var2 = ${var2}
...
My solution is:
class MyTemplateExceptionHandler implements TemplateExceptionHandler {
public void handleTemplateException(TemplateException te, Environment env, java.io.Writer out)
throws TemplateException {
try {
//2nd word on 2nd row is name of missing variable :(
String missingVariable = te.getMessageWithoutStackTop().split("\n")[1].split(" ")[1];
out.write("${" + missingVariable + "}");
} catch (IOException e) {
throw new TemplateException("Failed to print error message. Cause: " + e, env);
}
} }
and using:
...
Configuration cfg = new Configuration();
cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());
...
My solution works, but I am not satisfied because of:
1) getting missing variable in handleTemplateException() is horrible. Does exist better way how to get a name of missing variable?
2) Even if I have my own TemplateExceptionHandler, FreeMarker writes enough information to output. Can I change it?
Example output for missing variable "environment_name":
22.10.2014 9:01:55 freemarker.log._JDK14LoggerFactory$JDK14Logger error
SEVERE: Error executing FreeMarker template
FreeMarker template error:
The following has evaluated to null or missing:
==> environment_name [in template "Osb-PrepareAndDeploy.ftl" at line 33, column 33]
Tip: If the failing expression is known to be legally null/missing, either specify a default value with 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 parenthessis: (myOptionVar.foo)!myDefault, (myOptionVar.foo)??
The failing instruction (FTL stack trace):
----------
==> ${environment_name} [in template "Osb-PrepareAndDeploy.ftl" at line 33, column 31]
----------
Java stack trace (for programmers):
----------
freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...]
at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:98)
at freemarker.core.EvalUtil.coerceModelToString(EvalUtil.java:382)
at freemarker.core.Expression.evalAndCoerceToString(Expression.java:115)
at freemarker.core.DollarVariable.accept(DollarVariable.java:76)
at freemarker.core.Environment.visit(Environment.java:265)
at freemarker.core.MixedContent.accept(MixedContent.java:93)
at freemarker.core.Environment.visit(Environment.java:265)
at freemarker.core.Environment.process(Environment.java:243)
at freemarker.template.Template.process(Template.java:277)
at net.homecredit.scm.jenkinsTool.countrySettings.Country.createJobs(Country.java:282)
at net.homecredit.scm.jenkinsTool.Start.main(Start.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
You can't prevent the exception from being logged. TemplateExceptionHandler doesn't mean to make non-error from an error, it just lets you decide what to do after the error has happened. Like, you want to print an error page or something. In extreme case, you may want to continue page rendering after printing some error indicator, but that's still an error that need to be fixed.
Maybe it would help if you tell why do you need this. Maybe the solution isn't TemplateExceptionHandler-s.
As of more intelligent exception processing, first, in the handler you should check if the exception is a InvalidReferenceException, becaue I guess you don't want to deal with others. Then, with getBlamedExpressionString() (requires FreeMarker 2.3.21) you could get part of what you want to print to the output. It's only part of that, because if ${x + 1} fails because x is undefined, it will only return "x", not "x + 1".
Related
I'm working with what I believe is a fairly standard FusionAuth installation. From a few days ago, admin users have been unable to access the Dashboard at [myhost]:[myport]/admin/ (aside from this, FusionAuth appears to be working as normal).
Once a user has entered their login credentials, the page becomes unresponsive for some time (typically several minutes), before presenting them with this (obviously generic) message:
enter image description here
The StdErr logs show the following:
Jun 08, 2020 3:05:34 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [default] in context with path [] threw exception
org.primeframework.mvc.freemarker.FreeMarkerRenderException: freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:
==> loginData [in template "WEB-INF/templates/admin/index.ftl" at line 23, column 46]
The relevant section of index.ftl is as follows:
[#layout.html]
[#layout.head]
<script>
Prime.Document.onReady(function() {
new FusionAuth.Admin.Dashboard([[#list loginData.labels as label]"${label}"[#sep], [/#list]],
[[#list loginData.counts as count]${count}[#sep], [/#list]]);
});
</script>
[/#layout.head]
...and the loginData variable is declared as follows:
[#-- #ftlvariable name="loginData" type="io.fusionauth.app.service.ReportUtil.ReportData" --]
If a user enters the wrong password, they get the usual failure message, with little delay; this issue seems to occur after initial authentication. I understand that loginData is likely to be a report, but am uncertain of its significance (and the standard FusionAuth login report seems to work OK when I call the API via Postman). Has anyone had a similar issue?
Edit: I'm advised that this is a standard installation, with Elasticsearch and MySQL as recommended. User count isn't believed to be unusual (totals report gives globalRegistrations and totalGlobalRegistrations in the 7500 to 8500 range).
Additional information:
Versions:
OS: Windows Server 2019 Standard, V1809
MySql: 8.0
ElasticSearch:6.3.1
FusionAuth: 1.9.1
There have been no known recent deliberate changes to this FusionAuth system
When the error occurs, no error were initially reported in the JS Console, but I've now seen one relating to a missing "]", and the reason for this is that the error message seen below appears to have been inserted into the page source, presumably while it was being generated using a template:
<script>
var FusionAuth = FusionAuth || {};
FusionAuth.requestContextPath = '';
FusionAuth.loginURI = FusionAuth.requestContextPath + '/login';
</script>
<script>
Prime.Document.onReady(function() {
new FusionAuth.Admin.Dashboard([FreeMarker template error (DEBUG mode; use RETHROW in production!):
The following has evaluated to null or missing:
==> loginData [in template "WEB-INF/templates/admin/index.ftl" at line 23, column 46]
----
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: #list loginData.labels as label [in template "WEB-INF/templates/admin/index.ftl" at line 23, column 39]
~ Reached through: #nested [in template "WEB-INF/templates/_layouts/admin.ftl" in macro "head" at line 124, column 3]
~ Reached through: #layout.head [in template "WEB-INF/templates/admin/index.ftl" at line 20, column 1]
~ Reached through: #nested [in template "WEB-INF/templates/_layouts/admin.ftl" in macro "html" at line 14, column 3]
~ Reached through: #layout.html [in template "WEB-INF/templates/admin/index.ftl" at line 19, column 1]
----
Java stack trace (for programmers):
----
freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...]
at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134)
at freemarker.core.UnexpectedTypeException.newDesciptionBuilder(UnexpectedTypeException.java:85)
at freemarker.core.UnexpectedTypeException.<init>(UnexpectedTypeException.java:48)
at freemarker.core.NonHashException.<init>(NonHashException.java:49)
...
Possible cause: I do see some apparent MySQL timeouts, now that I come to check the StdOut logs rather than StdErr; maybe that's the issue; will confirm - scratch that; the latest case was not accompanied by any obvious MySQL-related log entries.
Latest full error message (some lines removed from stack trace to save space. This error was not preceded directly by anything in either the StdOut or StdErr logs; it was the day's first entry in the StdErr log):
Jun 11, 2020 9:55:13 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [default] in context with path [] threw exception
org.primeframework.mvc.freemarker.FreeMarkerRenderException: freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:
==> loginData [in template "WEB-INF/templates/admin/index.ftl" at line 23, column 46]
----
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: #list loginData.labels as label [in template "WEB-INF/templates/admin/index.ftl" at line 23, column 39]
~ Reached through: #nested [in template "WEB-INF/templates/_layouts/admin.ftl" in macro "head" at line 124, column 3]
~ Reached through: #layout.head [in template "WEB-INF/templates/admin/index.ftl" at line 20, column 1]
~ Reached through: #nested [in template "WEB-INF/templates/_layouts/admin.ftl" in macro "html" at line 14, column 3]
~ Reached through: #layout.html [in template "WEB-INF/templates/admin/index.ftl" at line 19, column 1]
----
at org.primeframework.mvc.freemarker.DefaultFreeMarkerService.render(DefaultFreeMarkerService.java:69)
...
at io.fusionauth.app.primeframework.FusionAuthMVCWorkflow.perform(FusionAuthMVCWorkflow.java:93)
...
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:
==> loginData [in template "WEB-INF/templates/admin/index.ftl" at line 23, column 46]
----
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: #list loginData.labels as label [in template "WEB-INF/templates/admin/index.ftl" at line 23, column 39]
~ Reached through: #nested [in template "WEB-INF/templates/_layouts/admin.ftl" in macro "head" at line 124, column 3]
~ Reached through: #layout.head [in template "WEB-INF/templates/admin/index.ftl" at line 20, column 1]
~ Reached through: #nested [in template "WEB-INF/templates/_layouts/admin.ftl" in macro "html" at line 14, column 3]
~ Reached through: #layout.html [in template "WEB-INF/templates/admin/index.ftl" at line 19, column 1]
----
at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134)
...
at org.primeframework.mvc.freemarker.DefaultFreeMarkerService.render(DefaultFreeMarkerService.java:65)
... 35 more
Work-around: If we go to, for example, [host:port]/admin/user (ie. specify a page other than the Dashboard), the actual admin functionality can be used as normal.
NB A similar issue occurs if we attempt to use [host:port]admin/system/login-record/
Possible query issue
We have notices that the following query - which is believed to be the one that pulls the login data involved in this issue - is running slowly and locking up database connections:
SELECT
rl.applications_id AS applicationId,
rl.instant AS instant,
rl.ip_address AS ipAddress,
rl.users_id AS userId,
a.name AS applicationName,
COALESCE(i.email, i.username) AS loginId
FROM raw_logins AS rl
INNER JOIN applications AS a ON a.id = rl.applications_id
INNER JOIN identities AS i ON i.users_id = rl.users_id
ORDER BY rl.instant DESC
LIMIT 5
OFFSET 0
Is this a standard FusionAuth query? Have performance issues been reported with it?
I'm having an issue in JMeter wherein I receive this error
2014/08/14 14:13:26 ERROR - jmeter.util.BeanShellInterpreter: Error invoking bsh method: eval Sourced file: inline evaluation of: ``String RequestUrl = vars.get("RequestUrl"); String[] params = RequestUrl.split(" . . . '' : Typed variable declaration
2014/08/14 14:13:26 WARN - jmeter.extractor.BeanShellPostProcessor: Problem in BeanShell script org.apache.jorphan.util.JMeterException: Error invoking bsh method: eval Sourced file: inline evaluation of: ``String RequestUrl = vars.get("RequestUrl"); String[] params = RequestUrl.split(" . . . '' : Typed variable declaration
I have no clue whats wrong, and the code otherwise seems to be working. Can anyone give me some advice?
Here is the block of code in question:
String RequestUrl = vars.get("RequestUrl");
String[] params = RequestUrl.split("\\?");
String RequestTask = params[1].split("\\&")[1].split("=")[1];
System.out.println(RequestTask);
vars.put("RequestTask",RequestTask);
it should probably be mentioned that the code is in a post processor, which is paired with an Xpath extractor for "RequestUrl"
Edited to include entire error
I don't see your URL and what does XPath query return but in any case your URL parsing logic looks flaky as it strongly dependent on parameters order and presence and may bite you back in future in case of request URL change i.e. extra parameter or changed parameters order or something encoded, etc.
See below for reference:
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import java.net.URI;
import java.util.List;
String url = vars.get("RequestUrl");
List params = URLEncodedUtils.parse(new URI(url), "UTF-8");
for (NameValuePair param : params) {
if (param.getName().equals("put your actual param name here")) {
vars.put("RequestTask", param.getValue());
}
}
Also it worth checking out How to use BeanShell: JMeter's favorite built-in component for troubleshooting tips. In general to localize error logging should be used like:
log.info("something");
log.error("something else");
So if you don't see message in the log than Beanshell wasn't able to execute the line and failed somewhere above.
Also Beanshell error messages aren't very informative, I use the following construction in my scripts:
try {
//script logic here
}
catch (Throwable ex) {
log.error("Failed to do this or that", ex);
}
So error stracktrace could be read in jmeter.log file.
Hope this helps.
Could you show the whole error?
Try adding one statement after the other to see which one is root cause.
I suppose you may be making hypothesis on results (array access) which may be cause of issue.
if you are coverting a VuGen recorded JMS script to JMeter, then you have to look for the lr functions copied which WILL throw this/similar error.
For eg: int orderlinecount = Integer.parseInt(lr.eval_string("strInt"));
You have to make sure your script is free of all lr - related functions in order for the jmeter to successfully executed your script.
I used JDOM1 before to parse xmls with xpath, and tired with the non-generic style, so I decide to try JDOM2, OK, everything works perfect for me ( the generic, XPathFactory, XPathExpression). then I try a xpath statement with contains function :
XPathExpression<Text> timeXpath = XPathFactory.instance().compile(
"./p[contains(.,'time:')]/text()", Filters.textOnly());
String time = timeXpath.evaluateFirst(div).getTextTrim();
then I got exeptions:
java.lang.IllegalStateException: Unable to evaluate expression. See cause
at org.jdom2.xpath.jaxen.JaxenCompiled.evaluateRawFirst(JaxenCompiled.java:200)
at org.jdom2.xpath.util.AbstractXPathCompiled.evaluateFirst(AbstractXPathCompiled.java:327)
at peace.org.tm.spider.star.DamaiStarSpider.syncStarTracks(DamaiStarSpider.java:123)
at peace.org.tm.spider.star.DamaiStarSpider.main(DamaiStarSpider.java:156)
Caused by: org.jaxen.UnresolvableException: Function :contains
at org.jaxen.SimpleFunctionContext.getFunction(SimpleFunctionContext.java:142)
at org.jaxen.ContextSupport.getFunction(ContextSupport.java:189)
at org.jaxen.Context.getFunction(Context.java:153)
at org.jaxen.expr.DefaultFunctionCallExpr.evaluate(DefaultFunctionCallExpr.java:183)
at org.jaxen.expr.DefaultPredicate.evaluate(DefaultPredicate.java:106)
at org.jaxen.expr.PredicateSet.evaluatePredicates(PredicateSet.java:188)
at org.jaxen.expr.DefaultLocationPath.evaluate(DefaultLocationPath.java:218)
then I tried:
XPathExpression<Text> timeXpath = XPathFactory.instance().compile(
"./p[fn:contains(.,'time:')]/text()", Filters.textOnly());
String time = timeXpath.evaluateFirst(div).getTextTrim();
xpath compile failed:
java.lang.IllegalArgumentException: Unable to compile './p[fn:contains(.,'time:')]/text()'. See Cause.
at org.jdom2.xpath.jaxen.JaxenCompiled.<init>(JaxenCompiled.java:152)
at org.jdom2.xpath.jaxen.JaxenXPathFactory.compile(JaxenXPathFactory.java:82)
at org.jdom2.xpath.XPathFactory.compile(XPathFactory.java:282)
at peace.org.tm.spider.star.DamaiStarSpider.syncStarTracks(DamaiStarSpider.java:91)
at peace.org.tm.spider.star.DamaiStarSpider.main(DamaiStarSpider.java:156)
Caused by: org.jaxen.XPathSyntaxException: Unexpected '('
at org.jaxen.BaseXPath.<init>(BaseXPath.java:136)
at org.jaxen.BaseXPath.<init>(BaseXPath.java:157)
at org.jdom2.xpath.jaxen.JaxenCompiled.<init>(JaxenCompiled.java:150)
... 4 more
I already google the stack trace for about 2 hours, nothing useful founded, I think maybe I made a very stupid mistake, is anyone can figure it out for me? thanks!
I can't reproduce the exceptions you are getting.... I am using JDOM 2.0.5 with Jaxen 1.1.6.
I have created the following:
public static void main(String[] args) {
Element root = new Element ("root");
Element p = new Element("p");
p.addContent(" Return this time: Boo! ");
root.addContent(p);
XPathExpression<Text> timeXpath = XPathFactory.instance().compile(
"./p[contains(.,'time:')]/text()", Filters.textOnly());
XPathDiagnostic<Text> xpd = timeXpath.diagnose(root, true);
System.out.println(xpd);
System.out.println(timeXpath.evaluateFirst(root).getTextTrim());
}
and it produces:
[XPathDiagnostic: './p[contains(.,'time:')]/text()' evaluated (first) against org.jdom2.Element produced raw=1 discarded=0 returned=1]
Return this time: Boo!
I believe you may have out-of-date Jaxen class libraries?
How to make sense of the boost::mpi error code? For instance, what does error code 834983239 mean?
...
mpi::communicator world;
mpi::request req = world.isend(1, 1, std::string("hello"));
while(!req.test()) {
boost::this_thread::sleep(boost::posix_time::seconds(1));
}
int errorCode = req.test()->error();
...
The error code is unlikely to be filled in if there was not an error (and the default behavior for Boost.MPI is to throw an exception on error, not return a code). You should not need to check error codes manually unless you have changed Boost.MPI's default error handling settings.
I am trying to call cudppSort to sort a set of keys/values. I'm using the following code to set up the sort algorithm:
CUDPPConfiguration config;
config.op = CUDPP_ADD;
config.datatype = CUDPP_UINT;
config.algorithm = CUDPP_SORT_RADIX;
config.options = CUDPP_OPTION_KEY_VALUE_PAIRS | CUDPP_OPTION_FORWARD | CUDPP_OPTION_EXCLUSIVE;
CUDPPHandle planHandle;
CUDPPResult result = cudppPlan(&planHandle, config, number_points, 1, 0);
if (CUDPP_SUCCESS != result) {
printf("ERROR creating CUDPPPlan\n");
exit(-1);
}
The program exits, however on the line:
CUDPPResult result = cudppPlan(&planHandle, config, number_points, 1, 0);
and prints to stdout:
Cuda error: allocScanStorage in file 'c:/the/path/to/release1.1/cudpp/src/app/scan_app.cu' in line 279 : invalid configuration argument.
I looked at the line in scan_app.cu. It is,
CUT_CHECK_ERROR("allocScanStorage");
So apparently my configuration has an error that is causing the allocScanStorage to bomb out. There are only two calls to CUDA_SAFE_CALL in the function and I don't see a reason why either has anything to do with the configuration.
What is wrong with my configuration?
So that this doesn't sit around as an unanswered question (I'm not sure if this is the right SO etiquette but it seems like an answered question shouldn't sit around unanswered...), I'm copying the comment I made above here as an answer since it was the solution:
I figured this out (I'm still learning CUDA at the moment.) Because the error checking is asynchronous errors can show up in strange places if you don't check for them from time to time. My code had caused an error before I called cudppPlan but because I didn't check for errors the cudppPlan reported the error as if it was in cudppPlan.