Wiki source code of WebObjects with Scala

Last modified by Ravi Mendis on 2011/05/10 02:10

Hide last authors
Ravi Mendis 21.1 1 === What is Scala? ===
Ravi Mendis 195.1 2
Ravi Mendis 533.1 3 [[Scala>>url:http://www.scala-lang.org/||shape="rect"]] is a modern, multi-paradigm JVM language that is most often compared to [[Groovy>>url:http://en.wikipedia.org/wiki/Groovy_(programming_language)||shape="rect"]], [[Clojure>>url:http://en.wikipedia.org/wiki/Clojure||shape="rect"]] and [[Erlang>>url:http://en.wikipedia.org/wiki/Erlang_(programming_language)||shape="rect"]]. Its [[functional language>>url:http://en.wikipedia.org/wiki/Functional_programming||shape="rect"]] foundations and built-in [[Actors>>url:http://en.wikipedia.org/wiki/Actor_model||shape="rect"]] library make it especially attractive for concurrent computing. (Scala is an abbreviation for "scalable" hinting at its design goals).
Ravi Mendis 195.1 4
Ravi Mendis 533.1 5 In this day and age of multi-core processors concurrent computing can not be ignored. Many of the design features of Scala have been chosen with concurrency in mind, some of which may not be unfamiliar to Objective-C or WebObjects developers. Here's a summary:
Ravi Mendis 294.1 6
Ravi Mendis 533.1 7 |=(((
8
9 )))|=(((
10 Objective-C
11 )))|=(((
12 Java
13 )))|=(((
14 Scala
15 )))
16 |=(((
17 Immutability
18 )))|(((
19 Partial - via collections //e.g: NSArray/NSMutableArray//
20 )))|(((
21 No
22 )))|(((
23 Yes
24 )))
25 |=(((
26 Closures
27 )))|(((
28 Yes - via Blocks (//Extension//)
29 )))|(((
30 No
31 )))|(((
32 Yes - via Anonymous Functions
33 )))
34 |=(((
35 Static variables
36 )))|(((
37 Yes
38 )))|(((
39 Yes
40 )))|(((
41 No
42 )))
43 |=(((
44 Static methods
45 )))|(((
46 Yes
47 )))|(((
48 Yes
49 )))|(((
50 No
51 )))
52 |=(((
53 Concurrency
54 )))|(((
55 Yes - viaĀ [[Grand Central Dispatch>>url:http://en.wikipedia.org/wiki/Grand_Central_Dispatch||shape="rect"]] (//Extension//)
56 )))|(((
57 //Yes - via Threads//
58 )))|(((
59 Yes - viaĀ [[Actors>>url:http://en.wikipedia.org/wiki/Actor_model||shape="rect"]]
60 )))
61 |=(((
62
63 )))|=(((
64 Weakly Typed
65 )))|=(((
66 (% style="text-decoration: line-through;" %)Strongly Typed
67 )))|=(((
68 Strongly Typed
69 )))
Ravi Mendis 513.1 70
Ravi Mendis 294.1 71 Other notable features include:
72
Ravi Mendis 533.1 73 |=(((
74
75 )))|=(((
76 Objective-C
77 )))|=(((
78 Java
79 )))|=(((
80 Scala
81 )))
82 |=(((
83 Parametered methods
84 )))|(((
85 Yes //e.g: addObject: to~://
86 )))|(((
87 No
88 )))|(((
89 Yes //e.g: add(object= ,to=)//
90 )))
91 |=(((
92 Class composition
93 )))|(((
94 Yes - via Categories
95 )))|(((
96 Yes - via Interfaces
97 )))|(((
98 Yes - via [[Traits>>url:http://en.wikipedia.org/wiki/Trait_(computer_science)||shape="rect"]]
99 )))
Ravi Mendis 294.1 100
Ravi Mendis 195.1 101 === Why Use Scala? ===
102
Pascal Robert 537.1 103 For WebObjects developers, Scala offers itself as a powerful, safe and easy-to-use solution for [[concurrent computing>>doc:documentation.Home.How-tos.WebObjects with Scala.Building Concurrent Applications with WebObjects and Scala.WebHome]]. (In other words, Scala Actors can be used for problems that would have normally required threads).
Ravi Mendis 195.1 104
Ravi Mendis 294.1 105 === Can WebObjects be Programmed In Scala? ===
Ravi Mendis 195.1 106
Ravi Mendis 288.1 107 Yes. It is very simple.
Ravi Mendis 533.1 108 By virtue of being a JVM-language, Scala compiles to java bytecode.
Ravi Mendis 195.1 109
Ravi Mendis 533.1 110 Furthermore, being a multi-paradigm language grants Scala easy WebObjects-interoperability.
111
112 ===== Caveats =====
113
114 Legacy tool support is often cited as a weak point. The [[Eclipse Scala plugin>>url:http://www.scala-ide.org||shape="rect"]] has been found to be slow at times and sometimes buggy.
115
Ravi Mendis 294.1 116 = WebObjects In Scala =
Ravi Mendis 195.1 117
Ravi Mendis 294.1 118 The following highlights some of the differences between Java and Scala in WebObjects:
Ravi Mendis 195.1 119
Ravi Mendis 294.1 120 == EOs in Scala ==
121
Ravi Mendis 519.1 122 === Thread-Safe Shared Vars ===
Ravi Mendis 294.1 123
Ravi Mendis 533.1 124 Scala doesn't have static variables or methods. Instead Scala employs the [[Singleton Pattern>>url:http://en.wikipedia.org/wiki/Singleton_pattern||shape="rect"]] which is built into the language and is **thread-safe**: a class can have a //Companion Object// that will allow you to achieve something equivalent to static variables - but better.
Ravi Mendis 294.1 125
Ravi Mendis 533.1 126 You don't have to worry about synchronizing access to shared mutable fields in a concurrent application.
127 (This is not however true when for example you have a {{code language="none"}}val{{/code}} declared as a {{code language="none"}}NSMutableArray{{/code}}. You will still have to synchronize when adding to or removing from this mutable field).
Ravi Mendis 519.1 128
Ravi Mendis 517.1 129 The following is an example of the use of a //Companion Object// for Talent in Scala instead of Talent static fields in Java.
Ravi Mendis 435.1 130
Ravi Mendis 517.1 131 Java:
Ravi Mendis 294.1 132
Ravi Mendis 533.1 133 {{code 0="java"}}
Ravi Mendis 517.1 134
Ravi Mendis 533.1 135 public class Talent extends EOGenericRecord {
Ravi Mendis 294.1 136 public static final String ENTITY_NAME = "Talent";
Ravi Mendis 533.1 137 }
Ravi Mendis 294.1 138
139 {{/code}}
140
Ravi Mendis 517.1 141 Scala:
Ravi Mendis 294.1 142
143 {{code}}
144
Ravi Mendis 533.1 145 object Talent {
Ravi Mendis 294.1 146 val ENTITY_NAME = "Talent"
Ravi Mendis 533.1 147 }
Ravi Mendis 294.1 148
149 {{/code}}
150
Ravi Mendis 517.1 151 This value will be accessed exactly the same way in both languages:
152
153 {{code}}
154
155 Talent.ENTITY_NAME
156
157 {{/code}}
158
Ravi Mendis 318.1 159 ==== Compacted imports ====
Ravi Mendis 308.1 160
Ravi Mendis 294.1 161 In Java:
162
Ravi Mendis 533.1 163 {{code 0="java"}}
Ravi Mendis 294.1 164
165 import com.webobjects.eocontrol.EOGenericRecord;
166 import com.webobjects.eocontrol.EORelationshipManipulation;
167
168 {{/code}}
169
170 In Scala:
171
172 {{code}}
173
174 import com.webobjects.eocontrol.{EOGenericRecord, EORelationshipManipulation}
175
176 {{/code}}
177
178 == WOComponents in Scala ==
179
180 ==== Compact Constructors ====
181
182 Scala allows for simpler use of multi-valued constructors than Java.
183
184 In Java:
185
Ravi Mendis 533.1 186 {{code 0="java"}}
Ravi Mendis 294.1 187
188 public class MenuHeader extends WOComponent {
189
190 public MenuHeader(WOContext aContext) {
191 super(aContext);
192 }
Ravi Mendis 533.1 193 }
Ravi Mendis 294.1 194
195 {{/code}}
196
197 In Scala:
198
199 {{code}}
200
Ravi Mendis 533.1 201 class MenuHeader(context: WOContext) extends WOComponent(context: WOContext)
Ravi Mendis 294.1 202
203 {{/code}}
204
205 ==== Simplified Exception Handling ====
206
207 Scala doesn't force you to catch exceptions unlike in Java.
Ravi Mendis 533.1 208 In addition, the syntax employs Scala's very powerful **pattern matching** to handle exceptions.
Ravi Mendis 294.1 209
210 In Java:
211
Ravi Mendis 533.1 212 {{code 0="java"}}
Ravi Mendis 294.1 213
214 try {
215 EditPageInterface epi = D2W.factory().editPageForNewObjectWithEntityNamed(_manipulatedEntityName, session());
216 epi.setNextPage(context().page());
217 nextPage = (WOComponent) epi;
218 } catch (IllegalArgumentException e) {
219 ErrorPageInterface epf = D2W.factory().errorPage(session());
220 epf.setMessage(e.toString());
221 epf.setNextPage(context().page());
222 nextPage = (WOComponent) epf;
223 }
224
225 {{/code}}
226
227 In Scala:
228
229 {{code}}
230
231 try {
232 var epi: EditPageInterface = D2W.factory.editPageForNewObjectWithEntityNamed(_manipulatedEntityName, session)
233 epi.setNextPage(context.page)
234 nextPage = epi.asInstanceOf[WOComponent]
235 } catch {
236 case e: IllegalArgumentException => {
237 var epf: ErrorPageInterface = D2W.factory.errorPage(session)
238 epf.setMessage(e.toString)
239 epf.setNextPage(context.page)
240 nextPage = epf.asInstanceOf[WOComponent]
241 }
242 }
243
244 {{/code}}
245
Ravi Mendis 517.1 246 ==== Scala Annotations vs. Generated Accessors ====
247
Ravi Mendis 533.1 248 Here's an example of accessing variables in the following languages:
Ravi Mendis 517.1 249
Ravi Mendis 533.1 250 |=(((
251
252 )))|=(((
253 Objective-C
254 )))|=(((
255 Java
256 )))|=(((
257 Scala
258 )))
259 |=(((
260 getter
261 )))|(((
Ravi Mendis 535.1 262 {{code language="none"}}
263 [WO:object name]
264 {{/code}}
Ravi Mendis 533.1 265 )))|(((
Ravi Mendis 535.1 266 {{code language="none"}}
267 object.name()
268 {{/code}}
Ravi Mendis 533.1 269 )))|(((
Ravi Mendis 535.1 270 {{code language="none"}}
271 object.name
272 {{/code}}
Ravi Mendis 533.1 273 )))
274 |=(((
275 setter
276 )))|(((
Ravi Mendis 535.1 277 {{code language="none"}}
278 [object setName:aName]
279 {{/code}}
Ravi Mendis 533.1 280 )))|(((
Ravi Mendis 535.1 281 {{code language="none"}}
282 object.setName(aName)
283 {{/code}}
Ravi Mendis 533.1 284 )))|(((
Ravi Mendis 535.1 285 {{code language="none"}}
286 object.name = aName
287 {{/code}}
Ravi Mendis 533.1 288 )))
Ravi Mendis 517.1 289
290 Of course in Java, we may generate WebObjects classes with "get" methods as well in order to stick to convention.
Ravi Mendis 533.1 291 In scala there is an additional convenience we may use to produce "get" and "set" methods in addition to the default Scala accessors - Scala Annotations.
Ravi Mendis 517.1 292
Ravi Mendis 533.1 293 E.g, in Main.scala we annotate our component keys with {{code language="none"}}@BeanProperty{{/code}} to automatically create public "set" and "get" methods.
294 These variables can then be accessed via //KVC//.
Ravi Mendis 517.1 295
296 {{code}}
297
298 import scala.reflect.BeanProperty
299
300 @BeanProperty var username = new String()
301 @BeanProperty var password = new String()
302 @BeanProperty var isAssistantCheckboxVisible = false
303
304 {{/code}}
305
306 == How to Use Scala Collections with EOF ==
307
Ravi Mendis 533.1 308 To use the Scala Collections API with an NSArray or NSDictionary you simply need to add an import:
Ravi Mendis 517.1 309
Ravi Mendis 533.1 310 {{code 0="java"}}
Ravi Mendis 517.1 311
Ravi Mendis 525.1 312 import scala.collection.JavaConversions._
313
Ravi Mendis 517.1 314 {{/code}}
315
Ravi Mendis 533.1 316 After that, you may access the typical Scala collection methods directly on NSArray. This employs a feature of Scala known asĀ implicit conversionsĀ to automagically cast a NSArray (a Java Iterable) into a Scala Iterable while leaving the actual object unchanged.
Ravi Mendis 308.1 317
Ravi Mendis 533.1 318 == How to Add Scala to a WO Project (in Eclipse) ==
Ravi Mendis 308.1 319
Ravi Mendis 535.1 320 [[doc:WOL.Home.WOLips.Adding Scala Support to a WOLips Project.WebHome]]
Ravi Mendis 513.1 321
Ravi Mendis 534.1 322 {{include/}}
323
Ravi Mendis 290.1 324 == WO Scala Example ==
325
Ravi Mendis 517.1 326 The following example is an almost 100% Scala WO app. In reality it is a mixed Java/Scala app:
Ravi Mendis 533.1 327 All the EO logic and WO components are in Scala.
328 Only the Application class remains Java.
Ravi Mendis 292.1 329
Ravi Mendis 517.1 330 It is based on the D2W Movies example.
331
Ravi Mendis 533.1 332 {{attachments patterns=".*zip"/}}
Ravi Mendis 294.1 333
334 === Setup ===
335
Ravi Mendis 533.1 336 1. [[Install the Scala eclipse IDE>>url:http://download.scala-ide.org/||shape="rect"]]
Ravi Mendis 294.1 337 1. Right-click on Application.java and run as a WOApplication (as usual).
338
Ravi Mendis 533.1 339 {{note}}
340 Application can be made into a Scala class as well, but then you will have to create a launcher in Eclipse manually.
341 {{/note}}
Ravi Mendis 294.1 342
Ravi Mendis 533.1 343 == EO Templates ==
Ravi Mendis 294.1 344
Ravi Mendis 533.1 345 When you create your {{code language="none"}}.eogen{{/code}} file, be sure to make the following changes in the EOGenerator Editor:
346
347 1. Point to the local [[Scala versions>>url:http://wiki.objectstyle.org/confluence/display/WOL/EOGenerator+Templates+and+Additions||shape="rect"]] of the .eotemplate files for {{code language="none"}}Entity{{/code}} and {{code language="none"}}_Entity{{/code}}
Ravi Mendis 294.1 348 1. Change the File Names Extension to "scala"
Ravi Mendis 517.1 349 1. In Destination Paths set the Superclass Package (e.g: base)
Ravi Mendis 294.1 350 1. Uncheck Java under Options
Ravi Mendis 517.1 351
352 == How to Build & Deploy a WebObjects Scala Project with Ant ==
353
Ravi Mendis 533.1 354 1. [[Download>>url:http://www.scala-lang.org/downloads||shape="rect"]] and install Scala
355 1. Set {{code language="none"}}scala.home{{/code}} (the location Scala has been installed onto) in the project {{code language="none"}}build.properties{{/code}} file
Ravi Mendis 538.1 356 1. [[Add the scalac task and properties>>doc:documentation.Home.How-tos.WebObjects with Scala.Configuring Ant to Build Scala with WebObjects.WebHome]] to the ant build.xml file
Ravi Mendis 533.1 357 1. Run from the project directory: {{code language="none"}}sudo ant clean install{{/code}}