- Another JavaEE application with Scala and TomEE
- How to use Intellij to run your Scala application with TomEE and JUnit
- How to debug Scala code with break points
Do you remember what these applications are for? PhotoDB is our photo manager application; FaceID is our user management system. PhotoDB delegates the user management to FaceID, so it can focus on photo management tasks; Msglnk is the messaging system of our solution. It holds the JavaMail configurations. That's how the other two applications send and receive emails without having any JavaMail knowledge.
All three applications are dummy. The intent is to give examples of JavaEE with different programming languages and JavaScript frameworks running on top of our dear Apache TomEE. This is what we have now:
Application | Back end | Front end |
---|---|---|
PhotoDB | Java | Backbone.js |
FaceID | Groovy | ExtJS |
Msglnk | Scala | YUI |
This blog post will show how to build, run and debug the Msglnk project with Intellij and the Scala plugin supported by Jetbrains. The next steps are platform independent. They assume that you have Java and Intellij installed in your computer. You don’t need to worry about downloading and installing Scala itself. The maven plugin (maven-scala-plugin) does it for you.
Download and build the application via IDE
First step: install the Intellij plugin for Scala. This plugin is not included in your Intellij during the installation process, but it is ridiculously easy to get it configured afterwards. This plugin makes Intellij Scala code aware.Open Intellij and go to the Plugins configuration window.
Click on "Browse repositories…"
Filter the "scala" plugins and right-click the one supported by Jetbrains. Select "Download and install". That’s it. I told you it was easy!
Click on "Check out from Version Control" and select "Git".
The "Git Repository URL" is https://github.com/tveronezi/msglnk.git. Select the "Parent Directory" and press "Clone".
Click on the "Enable Type-aware highlighting" link.
Go to "Maven Projects" -> "msglnk (root)" -> "Lifecycle" and dbl-click "install". Be patient because it may take some time. When you run the "install" command for the first time, maven downloads all the dependencies of the project, including the latest snapshot version of the TomEE server.
Once you see the "BUILD SUCCESS" message, go to the "msglnk/msglnk-resources/target" directory, copy and unzip the "tomee-runtime.tar.gz" archive in a directory of tour choice. Please note that the "target" directories are maven temporary locations. The "target" directories will be deleted after a mvn clean call.
Replace the content of the tomcat-users.xml configuration file by the text below.
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="solution-admin" />
<user username="admin" password="admin" roles="solution-admin" />
</tomcat-users>
Go to "Edit Configurations" -> "+" -> "TomEE Server" -> "Local"
Click "Configure" and say the location of your TomEE server.
Click "Fix" -> "msglnk-gui:war exploded"
Set the "Application context" to "/msglnk" and click ok
Preparing an email account
Msglnk manages emails. Therefore, it depends on an external POP/SMTP server in order to run the tests. It was designed to be used with gmail. Follow the official tutorial on how to enable POP and SMTP access to your gmail account (Available here). Once you have your gmail account ready, use the "msglnk/msglnk-web/src/test/resources/default-session.properties" file as template for the parameters of your account. ux_session_user_account=foo@bar.org
ux_session_user_password=foo_bar
mail.smtp.auth=true
mail.smtp.starttls.enable=true
mail.smtp.host=smtp.gmail.com
mail.smtp.port=587
mail.host=pop.gmail.com
mail.store.protocol=pop3s
mail.pop3s.auth=true
mail.pop3s.port=995
Create a system variable called MSGLNK_MAIL_SESSION_CONFIG with the location of the file above. In my case (linux), it would be...
export MSGLNK_MAIL_SESSION_CONFIG=/home/tveronezi/Documents/default-session.properties
It is time to run the application
It is all set to finally have some fun! Select one of the JUnit test classes and click "Run".Just like Java, you can put break points in your Scala code. Put a break point on it and click "Debug".
Evaluating the value of the variables |
We are ready to run the TomEE server. Click "Run TomEE".
Enter your username and password.
Done.
Note that if you want to use some break points, you can also run the "Debug" version of it. Try it!
Some examples of Scala JavaEE code
Here is a list of examples of how a Scala JaveEE application would look like.Entity Bean
package msglnk.data
import scala.reflect.BeanProperty
import javax.persistence._
@Entity
@Table(uniqueConstraints = Array(new UniqueConstraint(columnNames = Array("session_name"))))
class MailSession extends BaseEntity {
@Column(name = "session_name")
@BeanProperty
var name: String = _
@Column(nullable = false)
@Lob
@BeanProperty
var config: String = _
}
DTO
package msglnk.dto
import javax.xml.bind.annotation.{XmlElement, XmlAccessorType, XmlAccessType, XmlRootElement}
import scala.Predef.String
import scala.reflect.BeanProperty
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement
class EmailDto {
@XmlElement
@BeanProperty
var session: String = _
@XmlElement
@BeanProperty
var from: String = _
@XmlElement
@BeanProperty
var to: String = _
@XmlElement
@BeanProperty
var subject: String = _
@XmlElement
@BeanProperty
var text: String = _
}
MDB
package msglnk.mdb
import javax.ejb.{EJB, MessageDriven}
import org.slf4j.LoggerFactory
import javax.jms.{Message, MessageListener}
import msglnk.service.MailSessionService
import javax.annotation.security.RunAs
@MessageDriven(mappedName = "SendEmailQueue", messageListenerInterface = classOf[MessageListener])
@RunAs("solution-admin")
class SendEmailRequest extends MessageListener {
val LOG = LoggerFactory.getLogger(classOf[SendEmailRequest])
@EJB var mailSession: MailSessionService = _
def onMessage(message: Message) {
val sessionName = message.getStringProperty("sessionName")
val to = message.getStringProperty("to")
val subject = message.getStringProperty("subject")
val text = message.getStringProperty("text")
mailSession.sendMail(sessionName, to, subject, text)
}
}
REST
package msglnk.rest
import javax.ejb.Stateless
import javax.ws.rs.{POST, FormParam, Path, Produces}
import javax.inject.Inject
import msglnk.service.MailSessionService
@Path("/session")
@Produces(Array("application/json"))
@Stateless
class Session {
@Inject var mailService: MailSessionService = _
@POST
def save(@FormParam("name") name: String, @FormParam("config") config: String) {
mailService.saveSession(name, config)
}
}
EJB
package msglnk.service
import javax.ejb.Stateless
import javax.annotation.security.RolesAllowed
import javax.persistence.{NoResultException, Query, PersistenceContext, EntityManager}
import msglnk.data.BaseEntity
import collection.JavaConversions._
@Stateless
@RolesAllowed(Array("solution-admin"))
class BaseEAO {
@PersistenceContext(unitName = "mailPU")
var em: EntityManager = _
def findAll[T](cls: Class[T]): Set[T] = {
val queryStr = "SELECT e FROM %s e".format(cls.getName)
val query = em.createQuery(queryStr)
val list = query.getResultList.asInstanceOf[java.util.List[T]]
list.toSet
}
def findUniqueBy[T, E](cls: Class[T], name: String, value: E): Option[T] = {
val queryStr = "SELECT e FROM %s e WHERE e.%s = :pValue".format(cls.getName, name)
val query = em.createQuery(queryStr)
query.setParameter("pValue", value)
findUnique(cls, query)
}
def findById[T, E](cls: Class[T], value: E): Option[T] = {
val obj = em.find(cls, value)
if (obj == null) {
None
} else {
Some(cls.cast(obj))
}
}
def findUnique[T](cls: Class[T], query: Query): Option[T] = {
try {
Some(cls.cast(query.getSingleResult))
}
catch {
case nre: NoResultException => None
}
}
def create[T <: BaseEntity](bean: T): T = {
if (bean.getUid == null) {
em.persist(bean)
em.flush()
} else {
// We don't need to do anything.
// Changes made to the entity will be persisted once the transaction is committed.
}
bean
}
}
JUnit class
package msglnk.tests
import msglnk.data.MailSession
import msglnk.runners.AdminRunner
import msglnk.service.BaseEAO
import org.junit.Assert
import org.junit.Test
import javax.inject.Inject
import msglnk.BaseTest
import javax.ejb.{EJBTransactionRolledbackException, EJBException}
class MailSessionBeanTest extends BaseTest {
@Inject var adminRunner: AdminRunner = _
@Inject var baseEAO: BaseEAO = _
private def createSessionObj(name: String, config: String) = {
val bean: MailSession = new MailSession
bean.setName(name)
bean.setConfig(config)
bean
}
@Test
def name_should_be_unique() {
try {
adminRunner.run({
baseEAO.create(createSessionObj("session a", "aaaaa"))
baseEAO.create(createSessionObj("session a", "bbbbb"))
})
Assert.fail("Exception expected")
}
catch {
case e: EJBException => {
Assert.assertEquals(classOf[EJBTransactionRolledbackException], e.getCausedByException.getClass)
}
case _ => Assert.fail("EJBException expected")
}
}
@Test
def config_should_not_be_null() {
adminRunner.run({
baseEAO.create(createSessionObj("session not null", ""))
})
try {
adminRunner.run({
baseEAO.create(createSessionObj("session null", null))
})
Assert.fail("Exception expected")
}
catch {
case e: EJBException => {
Assert.assertEquals(classOf[EJBTransactionRolledbackException], e.getCausedByException.getClass)
}
case _ => Assert.fail("EJBException expected")
}
}
}
Resources
http://tomee.apache.org/Apache TomEE and security
http://www.scala-lang.org/
http://scala-tools.org/mvnsites/maven-scala-plugin/
http://www.jetbrains.com/idea/
No comments:
Post a Comment