im just starting with lift and scala and have a problem i dont realy understand.
i have the folowing index.html
<html>
<head><title>title</title></head>
<body>
<table>
<lift:Members.list>
<tr>
<td><m:nick/></td>
</tr>
</lift:Members.list>
</table>
</body>
</html>
And the following snippet:
class Members {
def list(xhtml: NodeSeq) =
Member.findAll.flatMap(member => bind("m",xhtml
,"nick" -> member.nickName
))
}
for some reason i get the following error. ive tried alot of things but cant get it to work. whats wrong?
XML Parsing Error: prefix not bound to a namespace
Location: http://localhost:8080/hazardlift-1.0-SNAPSHOT/
Line Number 8, Column 25:<td><m:nick></m:nick></td>
-----------------------------^
Maybe lift doesn't get how to handle your return value. Try forcing an implicit conversion to NodeSeq by specifing it as returntype.
....
def list(xhtml: NodeSeq) : NodeSeq =
....
I just found another cause of this error - an unresolved tag.
I had this HTML:
<div >
<h3>Request Information</h3>
<lift:DetailedRequestData.renderContent>
<f:rowTag></f:rowTag>
</lift:DetailedRequestData.renderContent>
</div>
I had written this for renderContent:
def renderContent(ns: NodeSeq): NodeSeq = {
val key = beginTrans(DisplayData.logger)
var result = ns
try {
var requestID = DisplayData.getParameter("request")
bind("f", ns, "rowTag" -> <p>Request ID: {requestID}</p>)
}
catch {
case t: Throwable => DisplayData.logger.error("[DetailedRequestData$.renderContent] ", t)
}
endTrans(DisplayData.logger, key)
result
}
Since I had not assigned the result of the bind to result, I was returning the unmodified NodeSeq and got the same prefix not bound to a namespace error. Changing the one statement to:
result = bind("f", ns, "rowTag" -> <p>Request ID: {requestID}</p>)
Yes, this was my own stupid fault, but by documenting the problem here, hopefully I will save someone else from having this same problem and not knowing why.
Related
I wrote a simple code to parse a large XML file ( extract lines, clean text, and remove any html tags from it) using Apache Spark.
I'm seeing a NullPointerException when calling .replaceAllIn on a string, which is non-null.
The funny thing is that I have no errors when I run the code locally, using input from disk, but I get a NullPointerException when I run the same code on AWS EMR, loading the input file from S3.
Here is the relevant code:
val HTML_TAGS_PATTERN = """<[^>]+>""".r
// other code here...
spark
.sparkContext
.textFile(pathToInputFile, numPartitions)
.filter { str => str.startsWith(" <row ") }
.toDS()
.map { str =>
Locale.setDefault(new Locale("en", "US"))
val parts = str.split(""""""")
var title: String = ""
var body: String = ""
// some code ommitted here
title = StringEscapeUtils.unescapeXml(title).toLowerCase.trim
body = StringEscapeUtils.unescapeXml(body).toLowerCase // decode xml entities
println("before replacing, body is: "+body)
// NEXT LINE TRIGGERS NPE
body = HTML_TAGS_PATTERN.replaceAllIn(body, " ") // take out htmltags
}
Things I've tried:
printing the string just before calling replaceAllIn to make sure it's not null.
making sure the Locale is not null
printing out the exception message, and stacktrace: it just tells me that that line is where the NullPointerException occurs. Nothing more
Things that are different between my local setup and AWS EMR:
in my local setup, I load the input file from disk, on EMR I load it from s3.
in my local setup, I run Spark in standalone mode, on EMR it's run in cluster mode.
Everything else is the same on my machine and on AWS EMR: Scala version, Spark version, Java version, Cluster configs...
I have been trying to figure this out for some hours and I can't think of anything else to try.
EDIT
I've moved the call to r() to within the map{} body, like this:
val HTML_TAGS_PATTERN = """<[^>]+>"""
// code ommited
.map{
body = HTML_TAGS_PATTERN.r.replaceAllIn(body, " ")
}
This also produces a NPE, wit the following stracktrace:
java.lang.NullPointerException
at java.util.regex.Pattern.<init>(Pattern.java:1350)
at java.util.regex.Pattern.compile(Pattern.java:1028)
at scala.util.matching.Regex.<init>(Regex.scala:191)
at scala.collection.immutable.StringLike$class.r(StringLike.scala:255)
at scala.collection.immutable.StringOps.r(StringOps.scala:29)
at scala.collection.immutable.StringLike$class.r(StringLike.scala:244)
at scala.collection.immutable.StringOps.r(StringOps.scala:29)
at ReadSOStanfordTokenize$$anonfun$2.apply(ReadSOStanfordTokenize.scala:102)
at ReadSOStanfordTokenize$$anonfun$2.apply(ReadSOStanfordTokenize.scala:72)
at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIterator.processNext(Unknown Source)
at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43)
at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$8$$anon$1.hasNext(WholeStageCodegenExec.scala:377)
at org.apache.spark.sql.execution.datasources.FileFormatWriter$SingleDirectoryWriteTask.execute(FileFormatWriter.scala:243)
at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$org$apache$spark$sql$execution$datasources$FileFormatWriter$$executeTask$3.apply(FileFormatWriter.scala:190)
at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$org$apache$spar
I think you should try putting the regex inline like bellow.
This is a bit of a lame solution, you should be able to define a constant, maybe put it in a global object or something. Im not sure where you are defining it that would be a problem. But remember spark serialises the code and runs it on distributed workers, so something could be going wrong with that.
rdd.map { _ =>
...
body = """<[^>]+>""".r.replaceAllIn(body, " ")
}
I get a very similar error when I run .r on a null String.
val x: String = null
x.r
java.lang.NullPointerException
java.util.regex.Pattern.<init>(Pattern.java:1350)
java.util.regex.Pattern.compile(Pattern.java:1028)
scala.util.matching.Regex.<init>(Regex.scala:223)
scala.collection.immutable.StringLike.r(StringLike.scala:281)
scala.collection.immutable.StringLike.r$(StringLike.scala:281)
scala.collection.immutable.StringOps.r(StringOps.scala:29)
scala.collection.immutable.StringLike.r(StringLike.scala:270)
scala.collection.immutable.StringLike.r$(StringLike.scala:270)
scala.collection.immutable.StringOps.r(StringOps.scala:29)
That error has slightly different line numbers, I think because of the scala version. Im on 2.12.2.
Thanks to Stephen's answer I found why I was getting a NPE on my UDF... I went this way (finding a match in my case):
def findMatch(word: String): String => Boolean = { s =>
Option(s) match {
case Some(validText) => if (word.toLowerCase.r.findAllIn(validText.toLowerCase).nonEmpty) true else false
case None => false
}
}
"<[^>]+>" was great, but I have one type of things in my HTML. it consists of a name of style and then parameters in between curly braces:
p { margin-top: 0px;margin-bottom: 0px;line-height: 1.15; }
body { font-family: 'Arial';font-style: Normal;font-weight: normal;font-size: 14.6666666666667px; }.Normal { telerik-style-type: paragraph;telerik-style-name: Normal;border-collapse: collapse; }.TableNormal { telerik-style-type: table;telerik-style-name: TableNormal;border-collapse: collapse; }.s_4C87DD5E { telerik-style-type: local;font-family: 'Arial';font-size: 14.6666666666667px;color: #000000; }.s_8D20FCAB { telerik-style-type: local;font-family: 'Arial';font-size: 14.6666666666667px;color: #000000;text-decoration: underline; }.p_53E06EE5 { telerik-style-type: local;margin-left: 0px; }
I tried to extract them using the following, but it didn't work:
"\{[^\}]+\}"
I am using a partial view to list the top 5 children of a specific node.
This works, but only if I put a div before the
foreach
eg
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
<div class="title">Test</div>
<ul>
#{
var ow = #owCore.Initialise(1085);
<div> </div>
var node = Umbraco.Content(1105);
foreach (var item in node
.Children.Where("Visible")
.OrderBy("Id descending")
.Take(5)
)
{
<li>#item.pageTitle</li>
}
}
</ul>
produces the expected unsorted list.
However, if I remove the empty div
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
Test
<ul>
#{
var ow = #owCore.Initialise(1085);
var node = Umbraco.Content(1105);
foreach (var item in node
.Children.Where("Visible")
.OrderBy("Id descending")
.Take(5)
)
{
<li>#item.pageTitle</li>
}
}
The error I get is
Compiler Error Message: CS1513: } expected
Source Error:
Line 113: } Line 114: } Line 115:}
Clear looks like too few closing '}'
Presumably the div forces the closing }?
I have checked owCore (it's a library of functions I am building in App_Code : however, I have stripped this back and it's now doing nothing just to make sure there are matched curly brackets:
#using Umbraco
#using Umbraco.Core.Models
#using Umbraco.Web
#functions{
public static int Initialise(int siteDocID){
return 0;
}
}
However, if I remove the #owCore code from the partial view
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
Test
<ul>
#{
var node = Umbraco.Content(1105);
foreach (var item in node
.Children.Where("Visible")
.OrderBy("Id descending")
.Take(5)
)
{
<li>#item.pageTitle</li>
}
}
</ul>
All is ok again.
Does that mean it's definitely an issue with the owCore or simply something else tripping the issue with mismatched {}
I have checked the template calling this partial view and can't find a problem.
This doesn't make sense. Can anyone explain?
Thanks!
This is actually more of a razor question.
You start your code block with #{ and by doing that you don't need the # in front of owCore. Removing it will make it render even without the <div> as the razor parser is no longer confused by the #.
I know about this and this, but the answers are very strange, and in any case, I am looking to understand why this particular approach does not work:
#myPackage.views.html.ol(
{
Hello
}, {
World
}
)
myPackage.views.html.ol.scala.html
#(ol:Html*)
<ol>
#for(li <- ol) {
<li>
(hi)
<span class="li-body">#li</span>
</li>
}
</ol>
Error:
not found: value Hello
I must lack fundamental understanding about the rules of the template engine, because this seems intuitively correct to me.
The # character marks the beginning of a dynamic statement, so you are no longer in template syntax. It's trying to interpret the arguments to the ol() function as straight Scala/Java code, not the template syntax.
It depends on what exactly you're trying to do, but here are two ways to do it. You could probably also use the #defining helper.
#myPackage.views.html.ol(Html("Hello"), Html("World"))
Another way is to define the Html blocks at the beginning of your view.
#html1 = { Hello }
#html2 = { <strong>World</strong> }
#main(){
#myPackage.views.html.ol(html1, html2)
}
estimatic's answer was correct.
Of what he presented, I would probably have used the #html1 = ... solution, but I found something else, which I hope will benefit some future reader.
HtmlVarArgs.scala
import play.api.templates.Html
import scala.collection.mutable.ListBuffer
class HtmlVarArgs(html: Html) {
private val templates = ListBuffer(html)
def apply(html: Html) = {
templates += html
this
}
def passTo(f: Seq[Html] => Html) = f(templates)
}
object HtmlVarArgs {
def apply(html: Html) = new HtmlVarArgs(html)
}
ol.scala.html
myPackage.views.html.ol.scala.html
#(ol:Html*)
<ol>
#for(li <- ol) {
<li>
(hi)
<span class="li-body">#li</span>
</li>
}
</ol>
And then I can use it in a template as follows:
#HtmlVarArgs {
Hello
} {
World
}.passTo(myPackage.views.html.ol.apply)
If I have a template like this:
<div class="lift:ThisIsMySnippet?option1=a_value;option2=another_value">
<div class="morestuff">
{embed}
</div>
</div>
and then a snippet like this:
class ThisIsMySnippet {
// I want option1's value!
}
How do I get those values?
I believe you can get the param values of a snippet via the S object like this:
val x = S.attr("option1")
In this case, x will be a Box[String], so if you want to get the value in a safe way you could do this:
val x = S.attr("option1") openOr "defaultValue"
Is there a way I can modify dynamically the param of a snippet?
E.g. If I call this URL
host:port/a_page?name=myname
I would like that my page look like this:
<div class="lift:surround?with=default;at=content">
<div class="lift:comet?type=MySnippet;name=myname" >
...
</div>
</div>
Is that even possible? I tried using some javascript in order to extract the param from the url and putting it in the class attribute of the div but in my understanding that won't work becase the scripts will always execute after lift framework does it's magic.
Thanks in advance! Any help is really appreciated.
I used both tips provided to make it work, like ajantis mentioned reading the param directly from snippet is the easiest way but doesnt work in a comet call. Rogach solution works.
So the solution is:
<div class="lift:Ex.wrap">
<div id="myid"></div>
</div>
def wrap = {
val name = "lift:comet?type=MySnippet;name=" + S.param("name").openOr("...")
"#myid" #> <div id="myid" class={name} ></div>
}
Why not just extract http parameter inside snippet processing? i.e.
def render = {
val name = S.param("name").openOr("...")
....
}
You can try wrapping that comet snippet in other snippet, which would transform xml and add that name=myname to class. Like:
<div class="lift:Ex.wrap">
<div class="lift:comet?type=MySnippet"></div>
</div>
class Ex {
def wrap = { (n: NodeSeq) =>
// example transformation
// AntiXML syntax
import com.codecommit.antixml._;
val comet = n \ "div" head;
val comet2 =
comet.copy(attrs = comet.attrs +
("class" -> (comet.attrs("class") + ";name=myname")))
n \ "div" updated (0, comet2) unselect
}
}