scala in a wild enterprise

Post on 22-Jun-2015

1.027 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Video: (in russian) http://www.youtube.com/watch?v=4pTDhgWW6ko

TRANSCRIPT

Scala in a wild enterpriseRafael Bagmanov ( Grid Dynamics )

the?

In what use cases (types of applications) does Scala make the least sense?

"Database front end, CRUD apps.

Most of the boring apps that are built with Struts and Spring"

David Pollak "Barriers to scala adoption" Infoq.com

OpenGenesisgithub.com/griddynamics/OpenGenesis

● open source - open-genesis.org

● 2 years of development

● > 50 KLOC of scala code

● successfully deployed to production in one

large american financial institution

● Buzzwords: continuous deployment, cloud,

chef, devops, aws, openstack

OpenGenesisDeployment orchestration tool

● Integration with legacy apps and data (lots of

SOAP and xml)

● sophisticated security policies

● IT department separated from development

team

● J2EE Containers everywhere

● Risk averse

Enterprise characteristics

Typical "lightweight" j2ee stack

Web layer

Service layer

Data access layer

DB

Spring MVC

Spring

JPA

j2ee stack. Scala edition

Web layer

Service layer

Data access layer

DB

Spring MVC + scala magic

Spring + scala implicits

JPA Squeryl

j2ee stack. Scala edition

Web layer

Service layer

Data access layer

DB

Spring MVC

Spring

Squeryl

WAR

j2ee stack. Scala edition + scala goodness

Web layer

Service layer

Data access layer

DB

Spring MVC

Spring

Squeryl

Workflow distributed engine

Akka

WAR

Service layer: Spring

● DI fits almost nicely with scala

Spring with scala

● DI fits almost nicely with scalaclass GenesisRestController {

@Autowired var genesisService: GenesisService = _

}

class GenesisRestController {

@BeanProperty var genesisService: GenesisService = _

}

class GenesisRestController (genesisService: GenesisService) {}

Spring with scala

● DI fits almost nicely with scala○ "Everything is a trait" approach can't be done

Spring with scala

● DI fits almost nicely with scala○ "Everything is a trait" approach can't be done

○ Be aware of type inference in @Configuration beantrait Service

class ServiceImpl extends Service

@Configuration

class ServiceContext {

@Bean def service = new ServiceImpl

}

Spring with scala

● DI fits almost nicely with scala○ "Everything is a trait" approach can't be done

○ Be aware of type inference in @Configuration beantrait Service

class ServiceImpl extends Service

@Configuration

class ServiceContext {

@Bean def service: Service = new ServiceImpl

}

Spring with scala

● DI fits almost nicely with scala

● Rich spring templates libraries.

Spring with scala

● DI fits almost nicely with scala

● Rich spring templates libraries.

springLdapTemplate.authenticate("user", "*", "password", new

AuthenticationErrorCallback {

def execute(e: Exception) {log.error(e)}

})

Spring with scala

● DI fits almost nicely with scala

● Rich spring templates libraries.

springLdapTemplate.authenticate("user", "*", "password", new

AuthenticationErrorCallback {

def execute(e: Exception) {log.error(e)}

})

Spring with scala

● DI fits almost nicely with scala

● Rich spring templates libraries.

springLdapTemplate.authenticate("user", "*", "password", new

AuthenticationErrorCallback {

def execute(e: Exception) {log.error(e)}

})

springLdapTemplate.authenticate("user", "*", "password", log.error(_))

Spring with scala

● DI fits almost nicely with scala

● Rich spring templates libraries.

springLdapTemplate.authenticate("user", "*", "password", log.error(_))

implicit def authErrorCallbackWrapper(func:(Exception) => Any) = { new AuthenticationErrorCallback { def execute(exception: Exception): Unit = func(exception) } }

Spring with scala

● DI fits almost nicely with scala

● Rich spring templates libraries.

● AOP for free (almost)

Spring with scala

● DI fits almost nicely with scala

● Rich spring templates libraries.

● AOP for free (almost)○ Be aware of naming in debug info def findUsers(projectId: Int) {

dao.findUsers(projectId)

}

def findUsers2(projectId: Int) {

dao.allUsers().filter(_.projectId == projectId)

}

Spring with scala

● DI fits almost nicely with scala

● Rich spring templates libraries.

● AOP for free (almost)○ Be aware of naming in debug info def findUsers(projectId: Int) { // debugIfo: name "projectId" dao.findUsers(projectId)

}

def findUsers2(projectId: Int) { // debugInfo: name "projectId$" dao.allUsers().filter(_.projectId == projectId)

}

Spring with scala

● DI fits almost nicely with scala

● Rich spring templates libraries.

● AOP for free (almost)

● Spring security just works

Spring with scala

Persistence layer: Squeryl

● Lightweight ORM written in scala

Squeryl

● Lightweight ORM written in scala

Squeryl

class Workflow(override val id: Int) extends KeyedEntity[Int]

● Lightweight ORM written in scala

Squeryl

class Workflow(override val id: Int) extends KeyedEntity[Int]

object GS extends Schema {

val workflows = table[Workflow]

}

● Lightweight ORM written in scala

Squeryl

class Workflow(override val id: Int) extends KeyedEntity[Int]

object GS extends Schema {

val workflows = table[Workflow]

}

def find(workflowId: Int) = from(GS.workflows)(w =>

where(w.id === workflowId)

select (w)

orderBy(w.id desc)

)

● Lightweight ORM written in scala○ First class support for scala collections, options, etc

Squeryl

● Lightweight ORM written in scala○ First class support for scala collections, options, etc

○ Integrates with spring transaction management

(not out of the box)

Squeryl

● Lightweight ORM written in scala○ First class support for scala collections, options, etc

○ Integrates with spring transaction management

(not out of the box)

Squeryl

@Transactional(propagation = REQUIRES_NEW)

def find(workflowId: Int) = from(GS.workflows)(w =>

where(w.id === workflowId)

select (w)

orderBy(w.id desc)

)

Squeryl

● Lightweight ORM written in scala

○ Likes heap in the same proportion as Hibernate does

hibernate squeryl

● Lightweight ORM written in scala

○ Likes heap in the same proportion as Hibernate does

○ Lot's of "black magic" in source code

Squeryl

● Lightweight ORM written in scala

● Internal scala DSL for writing queries○ Type safe queries - compile time syntax check

Squeryl

● Lightweight ORM written in scala

● Internal scala DSL for writing queries○ Lot's of "black magic" in source code

Squeryl

● Lightweight ORM written in scala

● Internal scala DSL for writing queries○ Lot's of "black magic" in source code

○ Fallback on native sql is not easy

Squeryl

● Lightweight ORM written in scala

● Internal scala DSL for writing queries○ Lot's of "black magic" in source code

○ Fallback on native sql is not easy

○ Lots of implicits drives IDE crazy and increases compilation time

Squeryl

● Lightweight ORM written in scala

● Internal scala DSL for writing queries○ Lot's of "black magic" in source code

○ Fallback on native sql is not easy

○ Lots of implicits drives IDE crazy and increase compilation time

○ The approach is somewhat flawed (opinion)

Squeryl

Web layer: Spring MVClift-json

scala magic

● RESTfull web services

Web layer

case class User (

@NotBlank username: String,

@Email @Size(min = 1, max = 256) email: String,

password: Option[String]

)

@Controller

@RequestMapping(Array("/rest/users"))

class UsersController {

@RequestMapping(method = Array(RequestMethod.POST))

@ResponseBody

def create(@RequestBody @Valid request: User): User = userService.create(request)

}

● RESTfull web services

● Easy to make Hypermedia REST with

implicits

Web layer

@Controller

@RequestMapping(Array("/rest/users"))

class UsersController {

import com.griddynamics.genesis.rest.links.Hypermedia._

@RequestMapping(method = Array(RequestMethod.POST))

@ResponseBody

def create(@RequestBody @Valid request: User): Hypermedia[User] = {

userService.create(request).withLink("/rest/users", LinkType.SELF)

}

Couple of words aboutAKKA

Ехал Акка через Акка

Смотрит Акка в Акка Акка

Сунул Акка Акка в Акка

Акка Акка Акка Акка *

* Ode to Akka in russian

Greatest challenge:

Greatest challenge:People

● Hiring is hard

Challenges

● Hiring is hard○ Scala is a talent attraction

Challenges

● Hiring is hard○ Scala is a talent attraction

○ In avg: 0.5 interview per month

Challenges

● Hiring is hard

● Settling team standards and code

convention

Challenges

● Hiring is hard

● Settling team standards and code

convention○ Tools are not there yet

Challenges

● Hiring is hard

● Settling team standards and code

convention○ Tools are not there yet

○ Between "OCaml" and "Java" fires

Challenges

● Hiring is hard

● Settling team standards and code

convention○ Tools are not there yet

○ Between "OCaml" and "Java" fires

○ "Effective scala" by Twitter and "Scala style guide"

might help (a bit)

Challenges

The greatest code-review mystery of all times

if (option.isDefined) {

..

}

option.foreach { .. }

option match { case Some(x) => .. case None => ..}

How to deal with scala.Option

?

The greatest code-review mystery of all times

if (option.isDefined) {

..

}

option.foreach { .. }

option match { case Some(x) => .. case None => ..}

How to deal with scala.Option

?

Recruiting java developers

aka

5 stages of grief

1. Denial

2. Anger

3. Bargaining

4. Depression

5. Acceptance

5 stages of grief

1. Denial

2. Anger

3. Bargaining

4. Depression

5. Acceptance

5 stages of grief

1. Denial

2. Anger

3. Bargaining

4. Depression

5. Acceptance

5 stages of grief

1. Denial

2. Anger

3. Bargaining

4. Depression

5. Acceptance

5 stages of grief

1. Denial

2. Anger

3. Bargaining

4. Depression

5. Acceptance

5 stages of grief

1. Denial

2. Anger

3. Bargaining

4. Depression

5. Acceptance

5 stages of grief

top related