Using scala-js-env-selenium for crossbrowser testing - scala.js

I am using https://github.com/scala-js/scala-js-env-selenium for in-browser testing, so far tests are running fine in local browser. Now i want to run my tests in remote browsers (https://app.crossbrowsertesting.com)
I created new CrossBrowser
import org.openqa.selenium.remote.{DesiredCapabilities, RemoteWebDriver}
import org.scalajs.jsenv.selenium.{BrowserDriver, SeleniumBrowser}
import java.net.URL
object CrossBrowser {
def apply(): CrossBrowser = new CrossBrowser
val username = "email"
// Your username
val authkey = "xxxxxxxxxx" // Your authkey
}
class CrossBrowser private() extends SeleniumBrowser {
def name: String = "RemoteBrowser"
def newDriver: BrowserDriver = new CrossDriver
private class CrossDriver extends BrowserDriver {
protected def newDriver(): RemoteWebDriver = {
val caps = new DesiredCapabilities()
caps.setCapability("name", "Selenium Test Example")
caps.setCapability("build", "1.0")
caps.setCapability("browser_api_name", "IE10")
caps.setCapability("os_api_name", "Win7x64-C2")
caps.setCapability("screen_resolution", "1024x768")
caps.setCapability("record_video", "true")
caps.setCapability("record_network", "true")
new RemoteWebDriver(new URL("http://" + CrossBrowser.username + ":" + CrossBrowser.authkey + "#hub.crossbrowsertesting.com:80/wd/hub"), caps)
}
}
}
and updated build settings
jsEnv := new org.scalajs.jsenv.selenium.SeleniumJSEnv(CrossBrowser()),
jsEnv in Test := new org.scalajs.jsenv.selenium.SeleniumJSEnv(CrossBrowser())
when i ran test command i got following output
[trace] Stack trace suppressed: run last client/test:loadedTestFrameworks for the full output.
[error] (client/test:loadedTestFrameworks) org.openqa.selenium.WebDriverException: [fc92901a-f56a-4e4b-9d75-953402cbfe35] Test has timed out after 199 seconds
[error] Command duration or timeout: 199.20 seconds
[error] Build info: version: '2.53.0', revision: '35ae25b1534ae328c771e0856c93e187490ca824', time: '2016-03-15 10:43:46'
[error] System info: host: 'Chandras-MacBook-Pro.local', ip: 'xx.xx.xxx.x', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.11.3', java.version: '1.8.0_25'
[error] Driver info: org.openqa.selenium.remote.RemoteWebDriver
[error] Capabilities [{browserAttachTimeout=0, enablePersistentHover=true, ie.forceCreateProcessApi=false, pageLoadStrategy=normal, ie.usePerProcessProxy=false, ignoreZoomSetting=false, handlesAlerts=true, version=10, platform=WINDOWS, nativeEvents=true, ie.ensureCleanSession=false, elementScrollBehavior=0, ie.browserCommandLineSwitches=, webdriver.remote.sessionid=fc92901a-f56a-4e4b-9d75-953402cbfe35, requireWindowFocus=false, browserName=internet explorer, initialBrowserUrl=http://localhost:33793/, takesScreenshot=true, javascriptEnabled=true, ignoreProtectedModeSettings=false, enableElementCacheCleanup=true, cssSelectorsEnabled=true, unexpectedAlertBehaviour=dismiss}]
[error] Session ID: fc92901a-f56a-4e4b-9d75-953402cbfe35
Reason for time out is , test-runner tried to load file:/var/folders/n0/c0fyqlqx0gg15mv4t5mchgj80000gn/T/1464125278337-0/scalajsRun.html on remote machine which doesn't exist.
is it possible to do this kind of testing ..?(copy files to some server and load that url ..)

Selenium will need access to your files if you are running local tests. That's usually done via proxies. There seems to be support for local testing though (https://crossbrowsertesting.com/local-testing), you could try to contact them to set this up.

Related

Problems in the configuration between hadoop and spark

I have a problem in a program and I do not have this problem with spark-shell.
When I call:
FileSystem.get(spark.sparkContext.hadoopConfiguration)
In the spark-shell, everything works perfectly, but when I try to use it in the code, I can't read the core-site.xml. I still get it to work when I use:
val conf = new Configuration()
conf.addResource(new Path("path to conf/core-site.xml"))
FileSystem.get(conf)
This solution is not acceptable, since I need to use the Hadoop configuration without passing the configuration explicitly.
Both in (Spark-shell and in the program) the master is called with the parameters spark: //x.x.x.x: 7077
How can I configure spark to use the hadoop configuration?
Code:
val HdfsPrefix: String = "hdfs://"
val path: String = "/tmp/"
def getHdfs(spark: SparkSession): FileSystem = {
//val conf = new Configuration()
//conf.addResource(new Path("/path to/core-site.xml"))
//FileSystem.get(conf)
FileSystem.get(spark.sparkContext.hadoopConfiguration)
}
val dfs = getHdfs(session)
data.select("name", "value").collect().foreach{ x =>
val os = dfs.create(new Path(HdfsPrefix + path + x.getString(0)))
val content: String = x.getString(1)
os.write(content.getBytes)
os.hsync()
}
Error log:
Wrong FS: hdfs:/tmp, expected: file:///
java.lang.IllegalArgumentException: Wrong FS: hdfs:/tmp, expected: file:///
at org.apache.hadoop.fs.FileSystem.checkPath(FileSystem.java:645)
at org.apache.hadoop.fs.RawLocalFileSystem.pathToFile(RawLocalFileSystem.java:80)
at org.apache.hadoop.fs.RawLocalFileSystem.mkdirs(RawLocalFileSystem.java:428)
at org.apache.hadoop.fs.ChecksumFileSystem.mkdirs(ChecksumFileSystem.java:690)
at org.apache.hadoop.fs.ChecksumFileSystem.create(ChecksumFileSystem.java:446)
at org.apache.hadoop.fs.ChecksumFileSystem.create(ChecksumFileSystem.java:433)
at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:908)
at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:889)
at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:786)
at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:775)
at com.bbva.ebdm.ocelot.io.hdfs.HdfsIO$HdfsOutputFile$$anonfun$write$1.apply(HdfsIO.scala:116)
at com.bbva.ebdm.ocelot.io.hdfs.HdfsIO$HdfsOutputFile$$anonfun$write$1.apply(HdfsIO.scala:115)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
at com.bbva.ebdm.ocelot.io.hdfs.HdfsIO$HdfsOutputFile.write(HdfsIO.scala:115)
at com.bbva.ebdm.ocelot.templates.spark_sql.SparkSqlBaseApp$$anonfun$exec$1.apply(SparkSqlBaseApp.scala:33)
at com.bbva.ebdm.ocelot.templates.spark_sql.SparkSqlBaseApp$$anonfun$exec$1.apply(SparkSqlBaseApp.scala:31)
at scala.collection.immutable.Map$Map3.foreach(Map.scala:161)
at com.bbva.ebdm.ocelot.templates.spark_sql.SparkSqlBaseApp$class.exec(SparkSqlBaseApp.scala:31)
at com.bbva.ebdm.ocelot.templates.spark_sql.SparkSqlBaseAppTest$$anonfun$1$$anonfun$apply$mcV$sp$1$$anonfun$apply$1$$anonfun$2$$anonfun$apply$2$$anon$1.exec(SparkSqlBaseAppTest.scala:47)
at com.bbva.ebdm.ocelot.templates.spark_sql.SparkSqlBaseAppTest$$anonfun$1$$anonfun$apply$mcV$sp$1$$anonfun$apply$3.apply(SparkSqlBaseAppTest.scala:49)
at com.bbva.ebdm.ocelot.templates.spark_sql.SparkSqlBaseAppTest$$anonfun$1$$anonfun$apply$mcV$sp$1$$anonfun$apply$3.apply(SparkSqlBaseAppTest.scala:47)
at com.bbva.ebdm.ocelot.templates.spark_sql.SparkSqlBaseAppTest$$anonfun$1$$anonfun$apply$mcV$sp$1$$anonfun$apply$1.apply(SparkSqlBaseAppTest.scala:47)
at com.bbva.ebdm.ocelot.templates.spark_sql.SparkSqlBaseAppTest$$anonfun$1$$anonfun$apply$mcV$sp$1$$anonfun$apply$1.apply(SparkSqlBaseAppTest.scala:47)
at wvlet.airframe.Design.runWithSession(Design.scala:169)
at wvlet.airframe.Design.withSession(Design.scala:182)
at com.bbva.ebdm.ocelot.templates.spark_sql.SparkSqlBaseAppTest$$anonfun$1$$anonfun$apply$mcV$sp$1.apply(SparkSqlBaseAppTest.scala:47)
at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
at org.scalatest.Transformer.apply(Transformer.scala:22)
at org.scalatest.Transformer.apply(Transformer.scala:20)
at org.scalatest.FunSpecLike$$anon$1.apply(FunSpecLike.scala:454)
at org.scalatest.TestSuite$class.withFixture(TestSuite.scala:196)
at org.scalatest.FunSpec.withFixture(FunSpec.scala:1630)
at org.scalatest.FunSpecLike$class.invokeWithFixture$1(FunSpecLike.scala:451)
at org.scalatest.FunSpecLike$$anonfun$runTest$1.apply(FunSpecLike.scala:464)
at org.scalatest.FunSpecLike$$anonfun$runTest$1.apply(FunSpecLike.scala:464)
at org.scalatest.SuperEngine.runTestImpl(Engine.scala:289)
at org.scalatest.FunSpecLike$class.runTest(FunSpecLike.scala:464)
at org.scalatest.FunSpec.runTest(FunSpec.scala:1630)
at org.scalatest.FunSpecLike$$anonfun$runTests$1.apply(FunSpecLike.scala:497)
at org.scalatest.FunSpecLike$$anonfun$runTests$1.apply(FunSpecLike.scala:497)
at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:396)
at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:384)
at scala.collection.immutable.List.foreach(List.scala:392)
at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:384)
at org.scalatest.SuperEngine.org$scalatest$SuperEngine$$runTestsInBranch(Engine.scala:373)
at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:410)
at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:384)
at scala.collection.immutable.List.foreach(List.scala:392)
at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:384)
at org.scalatest.SuperEngine.org$scalatest$SuperEngine$$runTestsInBranch(Engine.scala:379)
at org.scalatest.SuperEngine.runTestsImpl(Engine.scala:461)
at org.scalatest.FunSpecLike$class.runTests(FunSpecLike.scala:497)
at org.scalatest.FunSpec.runTests(FunSpec.scala:1630)
at org.scalatest.Suite$class.run(Suite.scala:1147)
at org.scalatest.FunSpec.org$scalatest$FunSpecLike$$super$run(FunSpec.scala:1630)
at org.scalatest.FunSpecLike$$anonfun$run$1.apply(FunSpecLike.scala:501)
at org.scalatest.FunSpecLike$$anonfun$run$1.apply(FunSpecLike.scala:501)
at org.scalatest.SuperEngine.runImpl(Engine.scala:521)
at org.scalatest.FunSpecLike$class.run(FunSpecLike.scala:501)
at com.bbva.ebdm.ocelot.templates.spark_sql.SparkSqlBaseAppTest.org$scalatest$BeforeAndAfterAll$$super$run(SparkSqlBaseAppTest.scala:31)
at org.scalatest.BeforeAndAfterAll$class.liftedTree1$1(BeforeAndAfterAll.scala:213)
at org.scalatest.BeforeAndAfterAll$class.run(BeforeAndAfterAll.scala:210)
at com.bbva.ebdm.ocelot.templates.spark_sql.SparkSqlBaseAppTest.run(SparkSqlBaseAppTest.scala:31)
at org.scalatest.tools.SuiteRunner.run(SuiteRunner.scala:45)
at org.scalatest.tools.Runner$$anonfun$doRunRunRunDaDoRunRun$1.apply(Runner.scala:1346)
at org.scalatest.tools.Runner$$anonfun$doRunRunRunDaDoRunRun$1.apply(Runner.scala:1340)
at scala.collection.immutable.List.foreach(List.scala:392)
at org.scalatest.tools.Runner$.doRunRunRunDaDoRunRun(Runner.scala:1340)
at org.scalatest.tools.Runner$$anonfun$runOptionallyWithPassFailReporter$2.apply(Runner.scala:1011)
at org.scalatest.tools.Runner$$anonfun$runOptionallyWithPassFailReporter$2.apply(Runner.scala:1010)
at org.scalatest.tools.Runner$.withClassLoaderAndDispatchReporter(Runner.scala:1506)
at org.scalatest.tools.Runner$.runOptionallyWithPassFailReporter(Runner.scala:1010)
at org.scalatest.tools.Runner$.run(Runner.scala:850)
at org.scalatest.tools.Runner.run(Runner.scala)
at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.runScalaTest2(ScalaTestRunner.java:131)
at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.main(ScalaTestRunner.java:28)
You need to put the hdfs-site.xml, core-site.xml in spark class path i.e classpath of your program when you are running it
https://spark.apache.org/docs/latest/configuration.html#custom-hadoophive-configuration
According to doc's:
If you plan to read and write from HDFS using Spark, there are two Hadoop configuration files that should be included on Spark’s classpath:
hdfs-site.xml, which provides default behaviors for the HDFS client.
core-site.xml, which sets the default filesystem name.
The location of these configuration files varies across Hadoop versions, but a common location is inside of /etc/hadoop/conf. Some tools create configurations on-the-fly, but offer a mechanism to download copies of them.
To make these files visible to Spark, set HADOOP_CONF_DIR in $SPARK_HOME/conf/spark-env.sh to a location containing the configuration files.
The problem was 'ScalaTest', it doesn't read the core-site.xml when Maven is compiling the proyect, but spark-submit reads it correctly when the proyect is compiled.

How to overcome Scalatra initialization issue: NoSuchMethodError: javax.servlet.ServletContext.getFilterRegistration?

This is my first time using Scalatra, and I'm using it outside of SBT (building and running using mill). I get the following error which seems to be about a missing dependency.
2018.05.23 18:26:30 [main] INFO org.scalatra.servlet.ScalatraListener - The cycle class name from the config: ScalatraBootstrap
2018.05.23 18:26:30 [main] INFO org.scalatra.servlet.ScalatraListener - Initializing life cycle class: ScalatraBootstrap
2018.05.23 18:26:30 [main] ERROR org.scalatra.servlet.ScalatraListener - Failed to initialize scalatra application at
java.lang.NoSuchMethodError: javax.servlet.ServletContext.getFilterRegistration(Ljava/lang/String;)Ljavax/servlet/FilterRegistration;
at org.scalatra.servlet.RichServletContext.mountFilter(RichServletContext.scala:162)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:85)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:93)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:90)
at ScalatraBootstrap.init(ScalatraBootstrap.scala:8)
at org.scalatra.servlet.ScalatraListener.configureCycleClass(ScalatraListener.scala:66)
at org.scalatra.servlet.ScalatraListener.contextInitialized(ScalatraListener.scala:22)
at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized(ContextHandler.java:890)
at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:558)
at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:853)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:370)
at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1497)
at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1459)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:785)
at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:287)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:545)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:138)
at org.eclipse.jetty.server.Server.start(Server.java:419)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:108)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
at org.eclipse.jetty.server.Server.doStart(Server.java:386)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at com.example.JettyLauncher$.main(JettyLauncher.scala:20)
at com.example.JettyLauncher.main(JettyLauncher.scala)
Here are the dependencies I'm using:
val jettyVersion = "9.4.10.v20180503"
def ivyDeps = Agg(
ivy"org.scalatra::scalatra:2.6.3",
ivy"javax.servlet:servlet-api:2.5",
ivy"org.eclipse.jetty:jetty-server:$jettyVersion",
ivy"org.eclipse.jetty:jetty-servlet:$jettyVersion",
ivy"org.eclipse.jetty:jetty-webapp:$jettyVersion",
)
My JettyLauncher is a striaght copy from the web site, so far, except I changed the resourceBase to be something that actually exists (but it didn't help):
object JettyLauncher { // this is my entry object as specified in sbt project definition
def main(args: Array[String]) {
val port = if(System.getenv("PORT") != null) System.getenv("PORT").toInt else 5001
val server = new Server(port)
val context = new WebAppContext()
context setContextPath "/"
context.setResourceBase("repeater")
context.addEventListener(new ScalatraListener)
context.addServlet(classOf[DefaultServlet], "/")
server.setHandler(context)
server.start
server.join
}
}
My LifeCycle class is also fairly minimal:
class ScalatraBootstrap extends LifeCycle {
override def init(context: ServletContext) {
context mount (new RepeatAll, "/*")
}
}
UPDATE
I changed to using ScalatraServlet instead of ScalatraServlet, but get a similar issue:
2018.05.23 18:39:24 [main] ERROR org.scalatra.servlet.ScalatraListener - Failed to initialize scalatra application at
java.lang.NoSuchMethodError: javax.servlet.ServletContext.getServletRegistration(Ljava/lang/String;)Ljavax/servlet/ServletRegistration;
at org.scalatra.servlet.RichServletContext.mountServlet(RichServletContext.scala:127)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:84)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:93)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:90)
at ScalatraBootstrap.init(ScalatraBootstrap.scala:8)
Update 2
Another important part of the stacktrace I missed posting earlier:
2018.05.23 18:39:24 [main] WARN org.eclipse.jetty.webapp.WebAppContext - Failed startup of context o.e.j.w.WebAppContext#3d74bf60{/,file:///home/brandon/workspace/sbh/repeater,UNAVAILABLE}
java.lang.NoSuchMethodError: javax.servlet.ServletContext.getServletRegistration(Ljava/lang/String;)Ljavax/servlet/ServletRegistration;
at org.scalatra.servlet.RichServletContext.mountServlet(RichServletContext.scala:127)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:84)
at org.scalatra.servlet.RichServletContext.mount(RichServletContext.scala:93)
I tried putting a WEB-INF/web.xml under repeater as specified above, but same result.

Selenium script doesnot wait long enough for the time defined in explicit wait

I am writing a selenium script using TestNG framework. i have defined the explicit wait as 20 seconds before selenium throws the NoSuchElement exception. but script does not wait for the 20 second during the execution and throws exception in 41 milliseconds.
i want this script to wait(using explicit wait only) or search for web element for 20 seconds before throwing any exception.
Below is the script followed by the execution result.
public class para {
WebDriver driver;
#BeforeClass
void InvokeFF() {
System.setProperty("webdriver.gecko.driver",
"C:/Users/Vinay/workspace_n/EGuru/drivers/geckodriver.exe");
driver = new FirefoxDriver();
// driver.get("http://seleniumpractise.blogspot.in/2016/08/bootstrap-dropdown-example-for-selenium.html");
System.out.println("Firefox invoked");
System.out.println("Firefox thread:" + Thread.currentThread().getId());
}
#Test
void Auto() throws Exception {
WebDriverWait wait = new WebDriverWait(driver, 20);
driver.get("file:///C:/Users/Vinay/Desktop/Upload1.html");
WebElement elem = driver.findElement(By.xpath(".//*[#id='1']"));
wait.until(ExpectedConditions.visibilityOfElementLocated(By
.xpath(".//*[#id='1']")));
elem.click();
Runtime.getRuntime().exec("C:\\Users\\Vinay\\Desktop\\AutoUpload.exe");
}
Firefox invoked Firefox thread:1 Execution Started [Utils] Attempting
to create C:\Users\Vinay\workspace_n\EGuru\test-output\Default
suite\Default test.xml [Utils] Directory
C:\Users\Vinay\workspace_n\EGuru\test-output\Default suite exists:
true FAILED: Auto org.openqa.selenium.NoSuchElementException: Unable
to locate element: {"method":"xpath","selector":".//*[#id='1']"}
Command duration or timeout: 41 milliseconds For documentation on this
error, please visit:
http://seleniumhq.org/exceptions/no_such_element.html Build info:
version: '2.53.0', revision: '35ae25b', time: '2016-03-15 16:57:40'
System info: host: 'Vinay-PC', ip: '192.168.1.2', os.name: 'Windows
7', os.arch: 'amd64', os.version: '6.1', java.version: '1.8.0_101'
Driver info: org.openqa.selenium.firefox.FirefoxDriver Capabilities
[{applicationCacheEnabled=true, rotatable=false, handlesAlerts=true,
databaseEnabled=true, version=45.0.2, platform=WINDOWS,
nativeEvents=false, acceptSslCerts=true, webStorageEnabled=true,
locationContextEnabled=true, browserName=firefox,
takesScreenshot=true, javascriptEnabled=true,
cssSelectorsEnabled=true}] Session ID:
d40fc001-400c-473b-8213-078e641b3c7f
*** Element info: {Using=xpath, value=.//*[#id='1']} at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
WebElement elem = driver.findElement(By.xpath(".//*[#id='1']"));
wait.until(ExpectedConditions.visibilityOfElementLocated(By
.xpath(".//*[#id='1']")));
The above two lines need to be reversed in order. You are attempting to get the element without a wait, then telling the webdriver to wait until it's there.

Play Mailer plugin with Play 2.5

I am struggling with play mailer plugin. I found many references to configure play-mailer plugin to send email using gmail, but none worked.
Here are the details -
Play 2.5
Scala 2.11
mailer plugin - "com.typesafe.play" %% "play-mailer" % "5.0.0"
And here is my code:
application.conf:
play.mailer {
host="smtp.gmail.com"
port=587
ssl=no
tls=yes
user="pariXXXXXX#gmail.com"
password="XXXXXX"
debug=no
timeout=60
connectiontimeout=60
mock=false
}
Controller:
class HomeController #Inject() (
val messagesApi: MessagesApi,
val mailer:MailerClient)
extends Controller with I18nSupport {
def index = Action {
val bodyHtml = Some(views.html.mails.welcome("Pari").toString)
val email = Email(subject = "subject", from = "pari.XXXXX#gmail.com", to = List("pari.XXXXX#gmail.com"), bodyHtml = bodyHtml, bodyText = Some("Hello"), replyTo = None)
mailer.send(email)
Ok("Did you receive my email?")
}
}
Error:
Execution exception[[EmailException: Sending the email to the following server failed : smtp.gmail.com:587]]
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:280)
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:206)
at play.api.GlobalSettings$class.onError(GlobalSettings.scala:160)
at play.api.DefaultGlobal$.onError(GlobalSettings.scala:188)
at play.api.http.GlobalSettingsHttpErrorHandler.onServerError(HttpErrorHandler.scala:98)
at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:100)
at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:99)
at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:344)
at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:343)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
Caused by: org.apache.commons.mail.EmailException: Sending the email to the following server failed : smtp.gmail.com:587
at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1421)
at org.apache.commons.mail.Email.send(Email.java:1448)
at play.api.libs.mailer.SMTPMailer$$anon$2.send(MailerPlugin.scala:100)
at play.api.libs.mailer.CommonsMailer.send(MailerPlugin.scala:130)
at play.api.libs.mailer.SMTPMailer.send(MailerPlugin.scala:110)
at play.api.libs.mailer.SMTPDynamicMailer.send(MailerPlugin.scala:117)
at controllers.HomeController$$anonfun$index$1.apply(HomeController.scala:82)
at controllers.HomeController$$anonfun$index$1.apply(HomeController.scala:79)
at play.api.mvc.ActionBuilder$$anonfun$apply$14.apply(Action.scala:403)
at play.api.mvc.ActionBuilder$$anonfun$apply$14.apply(Action.scala:403)
Caused by: javax.mail.MessagingException: Exception reading response
at com.sun.mail.smtp.SMTPTransport.readServerResponse(SMTPTransport.java:2202)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1939)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:654)
at javax.mail.Service.connect(Service.java:317)
at javax.mail.Service.connect(Service.java:176)
at javax.mail.Service.connect(Service.java:125)
at javax.mail.Transport.send0(Transport.java:194)
at javax.mail.Transport.send(Transport.java:124)
at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1411)
at org.apache.commons.mail.Email.send(Email.java:1448)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.sun.mail.util.TraceInputStream.read(TraceInputStream.java:124)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at com.sun.mail.util.LineInputStream.readLine(LineInputStream.java:89)
at com.sun.mail.smtp.SMTPTransport.readServerResponse(SMTPTransport.java:2182)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1939)
Any thoughts?
P.S. I have enabled less secure access for gmail account as well.
You simply need to provide play mailer configuration in your application.conf as below
play.mailer.host= "smtp.gmail.com"
play.mailer.port= "46"
play.mailer.ssl= true
play.mailer.user="pari.XXXX#gmail.com"
play.mailer.password="XXXXXXXXXX"
I have replaced play.mailer block with smtp.mock. After this change I am getting email sent by application.
smtp.mock=false
smtp {
host="smtp.gmail.com" #example:
port="465" #example: 465
ssl=true
user="pari.XXXX#gmail.com"
password="XXXXXXXXXX"
from="XXXXXXX"
}
However, I am getting warning -
smtp is deprecated, use play.mailer instead
Anybody has any idea, how to configure mailer configs.
Thanks
Pari

How to run ScalaTest with Guice DI and Slick?

I don't know how to configure GuiceApplicationBuilder in such a way, that I am able to load controllers that require a DatabaseConfigProvider to be injected.
I'd like to specify an alternative postgres database for testing, or an in memory database (if that is possible).
Code
class User
extends MySpecs
with OneAppPerTest
{
override def newAppForTest( testData: TestData ) = new GuiceApplicationBuilder()
// Somehow bind a database here, I guess?
.build()
"A test" should "test" in
{
val result = Application.instanceCache[api.controller.User]
.apply( app )
.list()( FakeRequest() )
...
}
}
Stacktrace
[info] - should return an entity *** FAILED ***
[info] com.google.inject.ConfigurationException: Guice configuration errors:
[info]
[info] 1) No implementation for play.api.db.slick.DatabaseConfigProvider was bound.
[info] while locating play.api.db.slick.DatabaseConfigProvider
[info] for parameter 1 at api.controller.User.<init>(User.scala:22)
[info] while locating api.controller.User
[info]
[info] 1 error
[info] at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1042)
[info] at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1001)
[info] at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)
[info] at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:321)
[info] at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:316)
[info] at play.api.Application$$anonfun$instanceCache$1.apply(Application.scala:234)
[info] at play.api.Application$$anonfun$instanceCache$1.apply(Application.scala:234)
[info] at play.utils.InlineCache.fresh(InlineCache.scala:69)
[info] at play.utils.InlineCache.apply(InlineCache.scala:55)
[info] ...
You need to add a configuration to your GuiceApplicationBuilder(), then everything should be handled automatically by play framework. Something like this should help:
val app = new GuiceApplicationBuilder()
.configure(
Configuration.from(
Map(
"slick.dbs.YOURDBNAME.driver" -> "slick.driver.H2Driver$",
"slick.dbs.YOURDBNAME.db.driver" -> "org.h2.Driver",
"slick.dbs.YOURDBNAME.db.url" -> "jdbc:h2:mem:",
"slick.dbs.default.driver" -> "slick.driver.MySQLDriver$",
"slick.dbs.default.db.driver" -> "com.mysql.jdbc.Driver"
)
)
)
.in(Mode.Test)
.build()
There is a little bit of setting up in this approach but the final result is fair. First of all start with implementing your own GuiceApplicationLoader by extending it. See my answer how to implement it. Why your own application loader? You can specify different configs/modules per Prod/Dev/Test modes - as well as different data sources. Your main application.conf wouldn't have data source configured. Instead, you would move it to environment specific configurations which would be merged with main configuration by application loader anyway. Your dev.conf would look as follows:
slick.dbs {
default {
driver = "slick.driver.PostgresDriver$",
db {
driver = "org.postgresql.Driver",
url = "jdbc:postgresql://localhost:5432/dev",
user = "postgres"
password = "postgres"
}
}
}
And the trick now is to use same data source name, in this case default, for all other configurations (the database url, drivers, credentials etc. would be different). With such setup, your evolutions will be applied to your test and dev database. Your test.conf could look as follows:
slick.dbs {
default {
// in memory configuration
}
}
In your tests, use WithApplicationLoader with your custom application loader instead and thats it.
#RunWith(classOf[JUnitRunner])
class ApplicationSpec extends Specification {
"Application" should {
"return text/html ok for home" in new WithApplicationLoader(new CustomApplicationLoader) {
val home = route(FakeRequest(routes.ApplicationController.home())).get
status(home) must equalTo(OK)
contentType(home) must beSome.which(_ == "text/html")
}
}
}
Within the test itself, you have an access to app: Application value:
val service = app.injector.instanceOf(classOf[IService])