"value getOrElse is not a member of String" in template - scala

I have the following template code:
views/Login.scala.html:
#(loginForm: Form[views.Data])
#import mytemplates.loginform
#Main("") {
email:#loginform(loginForm("email"))
#*email:#loginForm("email").value.getOrElse("xyz")*#
}
views/mytemplates/loginform.scala.html:
#(emailField: Field)
#emailField.value.getOrElse("xyz")
views/Main.scala.html:
#(page: String)(content: Html)
<!DOCTYPE html>
<html>
<body>
#content
</html>
views/Data.java:
package views;
import play.data.validation.ValidationError;
import java.util.List;
public class Data {
public String email = "";
public Data() { }
public List<ValidationError> validate() {
return null;
}
}
Compiling the above is successful. But if line #*email:#loginForm("email").value.getOrElse("xyz")*# in Login.scala.html is uncommented compiling produces an value getOrElse is not a member of String error.
Why does this happen? I'd like to exclude the template mytemplates.loginform but can't get it to work.
edit: Following estmatic's advice I get the following:
views/Login.scala.html:
#loginForm("email").getClass: class play.data.Form$Field
#loginForm("email").valueOr("").getClass: class java.lang.String
views/mytemplates/loginform.scala.html:
#emailField.getClass: class play.core.j.PlayMagicForJava$$anon$1
#emailField.value.getClass: class scala.None$
I had to use valueOr("") in Login.scala.html otherwise a NullPointer execution exception would be produced. Clearly they are all different classes. I haven't used Play framework much and am not sure what this means.

Since it looks like you have a Java project, the framework is going to do some automatic conversions here and there between the Java classes and their Scala equivalent.
Try this out:
#loginForm("email").getClass()
#loginForm("email").value.getClass()
Make this change on both Login.scala.html and loginform.scala.html and you'll see that you are dealing with different classes in each scenario.
When you go through the loginform template your field.value will be wrapped in a scala.Some object, which is why .getOrElse compiles in that case. When you do it directly in the main view you never leave Java-class-world, so your field.value is returned directly as a String.
If you are using the latest version of Play then you should be able to use the Field.valueOr method instead of getOrElse.
#loginForm("email").valueOr("xyz")

Related

Citrus framework: How to make a soap response / citrus variable / citrus function return result available to java

I'm using Citrus 2.7.8 with Cucumber 2.4.0. I'm making a soap call and want to get the response and do some advanced parsing on it to validate a graphql response has matching values. (I understand how to do validations when it's something that just has one element, but I need something able to handle when there could be one or many elements returned (for example, 1 vehicle or 4 vehicles)). To make my validation very dynamic and able to handle many different 'quotes', I want to store the response to a Citrus variable and then make it available to java to read in the file and do the advanced parsing and validation.
The TestContext injection doesn't appear to currently work with cucumber (see https://github.com/citrusframework/citrus/issues/657) so I'm using the workaround here:
How to inject TestContext using TestRunner and cucumber to manually create the context. Without this I get a nullpointerexception on anything with the context.
I am able to use Citrus's message function to grab the soap response which is awesome. My echo statements in the console show that it successfully put the right value into the citrus variable. But I'm having problems making that available to java so that I can then open it up and parse through it.
I've scaled down my step definition file to just the pertinent code. My couple attempts are listed below along with the problems I encountered in their results.
Does anyone have any ideas on how I can successfully workaround the context issues and make my response available to java?
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import com.consol.citrus.Citrus;
import com.consol.citrus.annotations.CitrusFramework;
import com.consol.citrus.annotations.CitrusResource;
import com.consol.citrus.config.CitrusSpringConfig;
import com.consol.citrus.context.TestContext;
import com.consol.citrus.dsl.junit.JUnit4CitrusTestRunner;
import com.consol.citrus.dsl.runner.TestRunner;
import com.consol.citrus.ws.client.WebServiceClient;
import cucumber.api.java.en.When;
#ContextConfiguration(classes = CitrusSpringConfig.class)
public class CitrusSteps extends JUnit4CitrusTestRunner {
#CitrusFramework
private Citrus citrus;
#CitrusResource
private TestRunner runner;
#CitrusResource
private TestContext context;
#Autowired
private WebServiceClient getQuote;
#When("^I call getQuote with id \"([^\"]*)\"$")
public void i_call_getquote_with_id(String quoteId) throws Throwable {
context = citrus.createTestContext();
String soappayload = "my payload (taken out for privacy purposes)";
runner.soap(action -> action.client(getQuote)
.send()
.soapAction("getQuote")
.payload(soappayload));
runner.soap(action -> action.client(getQuote)
.receive()
.name("getQuoteResponseStoredMessage"));
//this bombs out on the context line with this: "com.consol.citrus.exceptions.CitrusRuntimeException: Unknown variable 'messageStoreGetQuoteResponse1'"
runner.variable("messageStoreGetQuoteResponse1", "citrus:message(getQuoteResponseStoredMessage.payload())");
runner.echo("First try: ${messageStoreGetQuoteResponse1}");
String firstTry = context.getVariable("messageStoreGetQuoteResponse1");
log.info("First Try java variable: " + firstTry);
//this bombs out on the context line with this: "com.consol.citrus.exceptions.CitrusRuntimeException: Unknown variable 'messageStoreGetQuoteResponse2'"
runner.createVariable("messageStoreGetQuoteResponse2", "citrus:message(getQuoteResponseStoredMessage.payload())");
runner.echo("Second try: ${messageStoreGetQuoteResponse2}");
String secondTry = context.getVariable("messageStoreGetQuoteResponse2");
log.info("Second Try java variable: " + secondTry);
//This stores the literal as the value - it doesn't store the message so it appears I can't use citrus functions within the context
context.setVariable("messageStoreGetQuoteResponse3", "citrus:message(getQuoteResponseStoredMessage.payload())");
String thirdTry = context.getVariable("messageStoreGetQuoteResponse3");
log.info("Third Try java variable: " + thirdTry);
}
}
A smart co-worker figured out a workaround for the injection not working w/ cucumber.
I replaced these two lines:
#CitrusResource
private TestContext context;
with these lines instead:
TestContext testContext;
public TestContext getTestContext() {
if (testContext == null) {
runner.run(new AbstractTestAction() {
#Override
public void doExecute(TestContext context) {
testContext = context;
}
});
}
return testContext;
}
Then within my step where I want the context, I can use the above method. In my case I wanted my message response, so I was able to use this and confirm that the response is now in my java variable:
String responseXML = getTestContext().getMessageStore().getMessage("getQuoteResponseStoredMessage").getPayload(String.class);
log.info("Show response XML: " + responseXML);

a C# class derived from a template

I am new to c#, recently I read the source of code of Oxygen not include(using dnspy), which have some confusing code. I tried google but nothing helpful can be found.
Threr is a class called ElementEntry derived from a template class YamlIO。
what confuse me is that this template take the parameter T same as the class ElementEntry.
I think this may cause some problem. Am I right?
public class YamlIO<T>
{
...
}
public class ElementEntry : YamlIO<ElementEntry>
{
...
}

How to access to an URL selector at a component level

Scenario: (AEM 6.3.2) I'm requesting a page with the selector "test1", like this:
http://localhost:4502/content/myapp/home.test1.html
This page have a parsys where I have drop a component "slider", so the component's path is: "/content/myapp/home/jcr:content/parsys/slider"
At the "slider" component level, how can I access to the "test1" selector?
I've tried different ways (SlingModel, WCMUsePojo, the "request" HTL Global Object...), but always get the same problem: the "request" I can access is the GET request of the component (GET "/content/myapp/home/jcr:content/parsys/slider.html") where the selector is not present.
You should use the method SlingHttpServletRequest##getPathInfo inherited from HttpServletRequest
In your example, if you make a request to:
http://localhost:4502/content/myapp/home.test1.html
Then in your component's Class (Use/SlingModel) you can call request.getPathInfo() which will return: /content/myapp/home.test1.html
Then you can parse that path using: com.day.cq.commons.PathInfo
Here is an example sling model:
package com.mycom.core.models;
import com.day.cq.commons.PathInfo;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.Self;
#Model(adaptables = SlingHttpServletRequest.class,
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class SampleModel {
#Self
SlingHttpServletRequest request;
public PathInfo getPathInfo() {
return new PathInfo(request.getPathInfo());
}
}
then in your HTML you can do:
<sly data-sly-use.sample="com.mycom.core.models.SampleModel"/>
<div>${sample.pathInfo.selectors # join=', '}</div>
An that will output: (based on your example path)
<div>test1</div>
Just checked the exact same component/code on another AEM instance (same version) and it's working... will check what can be causing the wrong behavior, but I guess the problem is solved!

Get Annotation Parameter with AspectJ

I read many question in this forum but nothing works.
public #interface MyAnnotation {
String value() default "";
Class[] exceptionList;
}
#MyAnnotation(value="hello", exceptionList={TimeOutException.class})
public void method() {}
#Aspect
public class MyAspect {
#Around("#annotation(MyAnnotation)")
public Object handle(ProceedingJoinPoint joinPoint, MyAnnotation myAnnotation) {
System.out.println(myAnnotation.exceptionList); // should print out TimeOutException
}
}
How can I get the value and the exceptionList of the #MyAnnotation while executing the advice?
I'm using Spring 4.0.6, AspectJ 1.7.4
The solution for this is making sure the advice method's parameter name match the parameter name in AspectJ expression. In my case, the advice method should look like this:
#Aspect
public class MyAspect {
#Around("#annotation(myAnnotation)")
public Object handle(ProceedingJoinPoint joinPoint, MyAnnotation myAnnotation) {
System.out.println(myAnnotation.exceptionList); // should print out TimeOutException
}
}
You are already almost there. Probably.
You are using the correct way to retrieve the annotation, so you have the values available.
Your problem - if I interpret the very minimalistic problem description(!) you only provide via the comment in your code snippet(!) correctly - is the (wrong) assumption that sticking an array of the type Class into System.out.println() will print out the names of the Classes it contains. It does not. Instead it prints information about the reference:
[Ljava.lang.Class;#15db9742
If you want the names of the Classes, you will have to iterate over the elements of that array and use .getName(), .getSimpleName() or one of the other name providing methods of Class.
Further information on how to print elements of an array is here:
What's the simplest way to print a Java array?
Granted, this whole answer could be entirely besides the point if the problem is that you are getting null values from the annotation fields. But since you have not provided an adequate problem description ("nothing works" is not a problem description!), we can only guess at what your problem is.

How to create a custom 404 page handler with Play 2.0?

What’s the preferred way to handle 404 errors with Play 2.0 and show a nice templated view?
You can override the onHandlerNotFound method on your Global object, e.g.:
object Global extends GlobalSettings {
override def onHandlerNotFound(request: RequestHeader): Result = {
NotFound(views.html.notFound(request))
}
}
Please note that there are really two different problems to solve:
Showing a custom 404 page when there is "no handler found", e.g. when the user goes to an invalid URL, and
Showing a custom 404 (NotFound) page as a valid outcome of an existing handler.
I think the OP was referring to #2 but answers referred to #1.
"No Handler Found" Scenario
In the first scenario, for "no handler found" (i.e. invalid URL), the other answers have it right but to be more detailed, per the Play 2.1 documentation as:
Step 1: add a custom Global object:
import play.api._
import play.api.mvc._
import play.api.mvc.Results._
object Global extends GlobalSettings {
override def onHandlerNotFound(request: RequestHeader): Result = {
NotFound(
views.html.notFoundPage(request.path)
)
}
}
Step 2: add the template. Here's mine:
#(path: String)
<html>
<body>
<h1>Uh-oh. That wasn't found.</h1>
<p>#path</p>
</body>
</html>
Step 3: tweak your conf/application.conf to refer to your new "Global". I put it in the controllers package but it doesn't have to be:
...
application.global=controllers.Global
Step 4: restart and go to an invalid URL.
"Real Handler can't find object" Scenario
In the second scenario an existing handler wants to show a custom 404. For example, the user asked for object "1234" but no such object exists. The good news is that doing this is deceptively easy:
Instead of Ok(), surround your response with NotFound()
For example:
object FruitController extends Controller {
def showFruit(uuidString: String) = Action {
Fruits.find(uuidString) match {
case Some(fruit) => Ok(views.html.showFruit(fruit))
// NOTE THE USE OF "NotFound" BELOW!
case None => NotFound(views.html.noSuchFruit(s"No such fruit: $uuidString"))
}
}
}
What I like about this is the clean separation of the status code (200 vs 404) from the HTML returned (showFruit vs noSuchFruit).
HTH
Andrew
If you want to do the same using Java instead of Scala you can do it in this way (this works for play framework 2.0.3):
Global.java:
import play.GlobalSettings;
import play.mvc.Result;
import play.mvc.Results;
import play.mvc.Http.RequestHeader;
public class Global extends GlobalSettings {
#Override
public Result onHandlerNotFound(RequestHeader request) {
return Results.notFound(views.html.error404.render());
}
}
Asumming that your 404 error template is views.html.error404 (i.e. views/error404.scala.html).
Please note that Play development team are making lots of efforts to move away from global state in Play, and hence GlobalSettings and the application Global object have been deprecated since version 2.4.
HttpErrorHandler.onClientError should be used instead of
GlobalSettings.onHandlerNotFound. Basically create a class that inherits from HttpErrorHandler, and provide an implementation for onClientError method.
In order to find out type of error (404 in your case) you need to read status code, which is passed as a one of the method arguments e.g.
if(statusCode == play.mvc.Http.Status.NOT_FOUND) {
// your code to handle 'page not found' situation
// e.g. return custom implementation of 404 page
}
In order to let Play know what handler to use, you can place your error handler in the root package or configure it in application.conf using play.http.errorHandler configuration key e.g.
play.http.errorHandler = "my.library.MyErrorHandler"
You can find more details on handling errors here: for Scala or Java.
This works in 2.2.1. In Global.java:
public Promise<SimpleResult> onHandlerNotFound(RequestHeader request) {
return Promise.<SimpleResult>pure(notFound(
views.html.throw404.render()
));
}
Ensure that you have a view called /views/throw404.scala.html
This works in 2.2.3 Play - Java
public Promise<SimpleResult> onHandlerNotFound(RequestHeader request) {
return Promise<SimpleResult>pure(Results.notFound(views.html.notFound404.render()));
}
html should be within /views/notFound404.scala.html
Dont forget to add Results.notFounf() and import play.mvc.Results;
For Java, if you want to just redirect to main page, I solved it by this.
#Override
public Promise<Result> onHandlerNotFound(RequestHeader request) {
return Promise.pure(redirect("/"));
}