31
Spring Scala Sneaking Scala into your corporation Brought to you by / Henryk Konsek @hekonsek

Spring Scala - files.meetup.comfiles.meetup.com/11921292/Spring Scala - Sneaking Scala into your... · Apache Camel Spring Scala (Spring Source aka VMware aka Pivotal) 7 years of

  • Upload
    others

  • View
    69

  • Download
    0

Embed Size (px)

Citation preview

Spring ScalaSneaking Scala into your corporation

Brought to you by / Henryk Konsek @hekonsek

About meopen source committer, evangelist and adopterApache CamelSpring Scala (Spring Source aka VMware aka Pivotal)

7 years of professional experienceArtegence aka FilmwebAssecoPitney BowesJava Black Beltfreelance consulting

About meHired by Red Hat (JBoss)

to work with JBoss Fuse stack:

Apache ServiceMixApache ActiveMQJBoss HornetQApache CamelApache CXF

http://jboss.org/jbossfuse

This talk1. Some context2. What is Spring Scala3. How to use Spring Scala4. Why use Spring Scala

1. Some contextInversion Of Control (IoC)Dependency Injection (DI)Spring

Spring guide for busydevelopers

Defining dependency to be used in application:@Configurationpublic class InvoiceDaoConfiguration { @Bean InvoiceDao invoiceDao() { return new InvoiceDao(); }

@Bean InvoiceService invoiceService() { return new InvoiceService(invoiceDao()); }}

Spring guide for busydevelopers

Using the dependency in the application:

public class InvoiceReportGenerator {

@Inject private InvoiceService invoiceService;

public List<Invoice> invoicesForMonth(int year, int month) { InvoiceQuery query = InvoiceQueries.year(year).month(month); return invoiceService.findInvoices(query); }

}

2. What is Spring Scalaofficial project from Spring Source (aka VMware, aka Pivotal)portfolioAPI for defining beans in Scalawrappers for existing Spring API (aka Pimp My Spring)

3. How to use Spring Scala

Defining beansclass MyScalaConfig extends FunctionalConfiguration { val dao = bean()(MyDao()) bean()(MyService(dao()))}

define bean of type MyDao and bean of type MyServiceMyDao is wired into MyService

Notice functions!

Defining beansclass MyScalaConfig extends FunctionalConfiguration { val dao = bean(){ MyDao() }

bean() { MyService(dao()) }}

We avoid hard-coding method names. We invoke them instead.

Defining beans - lifecycleclass MessageBrokerConfiguration extends FunctionalConfiguration { bean(name = "activemqBroker") { val broker = new BrokerService broker.addConnector("tcp://localhost:61616") broker } init { _.start() } destroy { _.stop() }}

Accessing beansval context = FunctionalConfigApplicationContext[MyScalaConfig]val service = context[MyService]

Config

(Globally) Accessing beans

object MyScalaConfig extends FunctionalConfiguration { val dao = bean()(MyDao()) val service = bean()(MyService(dao()))}

+ application bootstrap

object MyApp extends App { new FunctionalConfigApplicationContext(). registerConfigurations(MyScalaConfig)}

= global access

MyScalaConfig.service().myServiceMethod()

Or even global access on steroids!import MyScalaConfig._...service().myServiceMethod()

Pimping your existingcontexts

val xmlContext = new ClassPathXmlApplicationContext("classpath:beans.xml")val scalaContext = ApplicationContextConversions.toRichApplicationContext(xmlContext)val service = scalaContext[MyService]

For those who aren't easily frightened by implicit conversions:

import org.springframework.scala.context.ApplicationContextConversions._val xmlContext = new ClassPathXmlApplicationContext("classpath:beans.xml")val service = xmlContext[MyService]

Scala friendly API #1JmsTemplate

val connectionFactory : ConnectionFactory = ...val template = new JmsTemplate(connectionFactory)

Function callbacks instead of anonymous inner functions.

template.send("queue") { session: Session => session.createTextMessage("Hello World")}

Pattern matching friendly return types.

template.receive("queue") match { case Some(m: TextMessage) => println(m.getText) case None => println("No text message received")}

Scala friendly API #2JdbcTemplate

val template = new JdbcTemplate(dataSource)

Functions instead of callbacksval template.queryAndMap("SELECT login FROM USER") { (resultSet, rowNum) => "%d: %s".format(rowNum, resultSet.getString(1))}

Scala collections instead of java.util API

val users : Map[String,AnyRef] = template.queryForMap("SELECT * FROM USER")

Options instead of nullsval query = "SELECT login FROM USER WHERE id = ?"val login = template.queryForObject[String](query , 1) match { Some(login) None => "defaultLogin"}

Scala friendly API #3Aspect Oriented Programming

Defining aspects as (anonymous inner) classes is overkill.val loggerAdvice = (method: Method, args: Array[AnyRef], target: Any) => log.debug("Executing method {}", method.getName)

val savePointcut = (m: Method, c: Class[_]) => m.getName.startsWith("save")

What about wiring aspects into beans?advice target (new MyService) on savePointcut using loggerAdvice

Integrating with non-ScalaSpring

You can mix your existing Spring Config file into functionalconfiguration.

class PersonConfiguration extends FunctionalConfiguration { importClass[NameConfiguration]()

val john = bean() { new Person(getBean("firstName"), getBean("lastName")) }}

Mixing XML...

class PersonConfiguration extends FunctionalConfiguration { importXml("classpath:/cxf-config.xml")

bean() { CxfExposer[PeopleService] }}

4. Why use Spring ScalaYour snippets were nice, but give me a real reason to use this

library.

Rant #1I can use pure Java Config with Scala!

Yes, you can...

@Bean(initMethod = "this String has been refactored by an accident", destroyMethod = "I love to type method names soooo much" + "and detecting problems at runtime" + "instead of invoking methods in functions callbacks" + "and detecting problems at compilation time")BrokerService activemqBroker() { val broker = new BrokerService broker.addConnector("tcp://localhost:61616") broker}...jmsTemplate.send(queue, new MessageCreator() { public Message createMessage(Session session) throws JMSException { return session.createTextMessage("Verbosity FTW!"); }})

Rant #2Spring sucks! Cake/Dagger/MacWire FTW!

OK if you start greenfield projectCake alone won't solve your problemsyou can use Cake *and* Spring Scalahow likely is that your existing project uses Spring already?

Rant #3Using Spring in Scala is stupid.

Hi Boss, I think that all the Spring trainings,developers experience, knowHow, patterns,

practices we follow won't be needed anymore!Scala is the next big thing, so we want to drop

all of these. BTW Will you send my team toScala Days? I'm aware that our budget is tight,

but you know, we need to educate...

Rant #4But this is yet another jar in my classpath!

I don't know how to answer this in 2014...use Maven/Ivy/Gradle/SBT?don't deploy over Internet and watch YouTubedelete some porns from your HDD

Rant #5Spring Scala is not 100% type safe. Spring is not type safe.

Indeed, but Spring Scala is safer than raw Spring.

Evolve, don't be a rebel #1make yourself a favor, introduce Scala to your legacy project

pick a slice of your existing Spring applicationrewrite that slice in Scala

Evolve, don't be a rebel #2make yourself a favor, introduce Scala to your legacy project

need to implement new enhancement request for thecustomer?write it in Scala and integrate with the existing Springcodebase

Evolve, don't be a rebel #3make yourself a favor, introduce Scala to your legacy project

promote micro-services approachwrite your micro-service module in Scalawire it however you wantuse Spring Scala to expose your service to the shared (non-Scala) application context

Evolve, don't be a rebel #4respect human factor

not everybody has to be a hackersome people don't feel comfortable with Monads ;)some people will learn and adapt slower than the otherscreate core logic in Scala, let the others to build on it inJava/Spring

LinksSpring Scala project at GitHub

Spring Scala project forum

Introducing Spring Scala by Arjen Poutsma

Many thanks!