Skip to content

Instantly share code, notes, and snippets.

@sandermak
Created May 20, 2013 19:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sandermak/5614864 to your computer and use it in GitHub Desktop.
Save sandermak/5614864 to your computer and use it in GitHub Desktop.
{
"status_code": 200,
"data": {
"results": [
{
"domain": "missesdressy.com",
"initial_epoch": "1369033342000",
"h3": [
"Similar Items",
"Tell me more about this dress...",
"We will be in touch soon.",
"Share this dress with a friend",
"We'll send your message right along."
],
"site": "www.missesdressy.com",
"lastindexed": "20130520162024",
"last_indexed_epoch": "1369066824570",
"title": "Scala 47588 Dress - MissesDressy.com",
"initial": "20130520070222",
"summaryText": "Bust Place the measuring tape under your arms and run it around the fullest part of the bust line and across the shoulder blades. Waist Run the measuring tape around your natural waistline at the crease. Keep a finger’s distance between the tape and your",
"content": "Bust Place the measuring tape under your arms and run it around the fullest part of the bust line and across the shoulder blades. Waist Run the measuring tape around your natural waistline at the crease. Keep a finger’s distance between the tape and your body for a comfortable fit. Hips With your feet together, wrap the measuring tape around the fullest part of your hips/seat – around 8 to 9 inches below your waistline.",
"score": 29.18372,
"summaryTitle": "<B>Scala</B> 47588",
"type": "search",
"description": "Draw attention to your hidden beauty in 47588 by Scala Couture. This fashionable cocktail dress offers a strapless and sweetheart neckline. Sequined bodice adorns the form fitting bodice. The mid-thigh hem shows off your flawless legs.",
"cities": "null",
"lang": "en",
"url": "http://www.missesdressy.com/dresses/designers/scala-couture/47588",
"referrer": [
"facebook.com",
"t.co",
"direct"
],
"aggregate_link": "http://bit.ly/10fzjIT",
"lastseen": "20130520162005",
"page": "http://www.missesdressy.com/dresses/designers/scala-couture/47588",
"ogtitle": "Scala 47588 Dress - MissesDressy.com"
},
{
"domain": "stackoverflow.com",
"initial_epoch": "1369038419000",
"h2": [
"2 Answers",
"Your Answer",
"Not the answer you're looking for? Browse other questions tagged scala or ask your own question ."
],
"h3": [
"Community Bulletin",
"Related"
],
"site": "stackoverflow.com",
"lastindexed": "20130520175107",
"last_indexed_epoch": "1369072267699",
"title": "Why is the `unary_` prefix needed in scala? - Stack Overflow",
"initial": "20130520082659",
"summaryText": " postfix ! Remember: <B>Scala</B> doesn't actually have operators. There are two ways to call a method, either... an identifier: foo plus 1 foo + 1 Now it looks like <B>Scala</B> has a binary infix + operator, but it...",
"content": "The unary_ prefix for unary prefix operators is a bit misleading: it's more about the prefix part than the unary part. You need some way to distinguish !foo // unary prefix ! from foo! // unary postfix ! Remember: Scala doesn't actually have operators. There are two ways to call a method, either with a . or with whitespace: foo.bar(1, \"two\") foo bar(1, \"two\") And when you have a single argument, you can leave off the parentheses: foo plus(1) foo plus 1 Lastly, (almost) any character is legal in an identifier: foo plus 1 foo + 1 Now it looks like Scala has a binary infix + operator, but it actually doesn't. It's just a normal method called with normal method calling syntax. What I said above isn't fully true, however. If Scala didn't have support for operators and it all was just normal method calling, then 2 + 3 * 4 would evaluate to 20 (like it does in Smalltalk, Self and Newspeak for example) instead of 14. So, there is a little bit of support for operators in Scala (two little bits, actually). When a method is called with whitespace (so-called \"operator syntax\") instead of the . , and that method starts with an operator character, then Scala will respect operator precedence. And the other little bit of operator support is that there are some operators that you would like to have, but that cannot be easily expressed as a method call. It works fine for binary infix operators and unary postfix operators: foo op bar // same as: foo.op(bar) foo op // same as: foo.op But not for prefix or \"around-fix\" operators: !foo foo(bar) So, there are a couple of special syntactic sugar translation rules: !foo foo.unary_! // same for +, - and ~ foo(bar) foo.apply(bar) foo(bar) = 1 foo.update(bar, 1) foo += 1 foo.+=(1) // but if this doesn't compile, then the compiler will also try foo = foo.+(1) And the reason why there needs to be an underscore between the alphanumeric and the \"operator\" part in a method name is because you wouldn't know whether foo! means foo.! or this.foo! Thus, foo! as a method name is illegal, it needs to be called foo_! .",
"score": 11.869331,
"summaryTitle": "Why is the `unary_` prefix needed in <B>scala</B>?",
"type": "search",
"cities": "null",
"lang": "en",
"url": "http://stackoverflow.com/questions/16644988/why-is-the-unary-prefix-needed-in-scala",
"referrer": [
"t.co",
"direct",
"bit.ly"
],
"aggregate_link": "http://bit.ly/17SJLub",
"lastseen": "20130520175052",
"page": "http://stackoverflow.com/questions/16644988/why-is-the-unary-prefix-needed-in-scala"
},
{
"domain": "teatroallascala.org",
"initial_epoch": "1368799302000",
"h2": "Götterdämmerung",
"h3": "Discover Götterdämmerung",
"site": "www.teatroallascala.org",
"lastindexed": "20130520192158",
"keywords": " Der Ring des Nibelungen,Foto Gallery,Fotografie,Götterdämmerung,La Scala,Mailand,Milano,Milano Musica,opera,Teatro alla Scala,tickets,Wagner",
"last_indexed_epoch": "1369077718198",
"title": "Lohengrin - Pictures - Teatro alla Scala",
"initial": "20130517140142",
"summaryText": "Teatro alla <B>Scala</B> Academy",
"content": "Teatro alla Scala Academy",
"score": 4.609135,
"summaryTitle": "Pictures",
"type": "search",
"description": "Welcome to the website of the Teatro alla Scala in Milan, where you can book tickets online, view the season programme (opera, ballet, concert) and discover the theatre through videos and images.",
"cities": "null",
"lang": "en",
"url": "http://www.teatroallascala.org/en/season/opera-ballet/2012-2013/Gotterdammerung-Der-Ring-des-Nibelungen_cnt_27141.html",
"referrer": [
"t.co",
"direct"
],
"aggregate_link": "http://bit.ly/13swPnT",
"lastseen": "20130520192139",
"page": "http://www.teatroallascala.org/en/season/opera-ballet/2012-2013/gotterdammerung-der-ring-des-nibelungen_cnt_27141.html"
},
{
"domain": "skillsmatter.com",
"initial_epoch": "1369051461000",
"site": "skillsmatter.com",
"lastindexed": "20130520152059",
"keywords": "Fast track to Scala, scala, akka, event-driven middleware framework, scalable concurrent applications, fault tolerant, akka applications, routing systems, dispatchers, Typesafe, Philipp Haller, scaling",
"last_indexed_epoch": "1369063259230",
"title": "Skills Matter : Typesafe Scaling up with Akka and Scala",
"initial": "20130520120421",
"summaryText": "To benefit from this Akka course, you should have previous experience of <B>Scala</B>, as all the examples and exercises will be written in <B>Scala</B>. BRING YOUR OWN LAPTOP Important You are requested to bring your own laptop to this Akka course, so",
"content": "To benefit from this Akka course, you should have previous experience of Scala, as all the examples and exercises will be written in Scala. BRING YOUR OWN LAPTOP Important You are requested to bring your own laptop to this Akka course, so you learn how to develop in Akka within your own environment. If you are unable to bring a laptop for the course, please contact the sales team on +44 20 7183 9040 or email sales@skillsmatter.com",
"score": 2.6508954,
"summaryTitle": "Skills Matter : Typesafe Scaling up with Akka and <B>Scala</B>",
"type": "search",
"description": "Typesafe Scaling up with Akka and Scala: This two-day Scaling up with Akka and Scala course is what you need to get started building powerful concurre",
"cities": "null",
"lang": "en",
"url": "http://skillsmatter.com/course/scala/typesafe-scaling-up-with-akka-and-scala",
"referrer": [
"t.co",
"direct"
],
"aggregate_link": "http://bit.ly/15F74aU",
"lastseen": "20130520152041",
"page": "http://skillsmatter.com/course/scala/typesafe-scaling-up-with-akka-and-scala"
},
{
"domain": "ibm.com",
"initial_epoch": "1369076981000",
"h2": [
"My developerWorks:",
"My notifications:",
"Select a language:",
"Technical topics",
"Evaluation software",
"Community",
"Events",
"About this series",
"Table of contents",
"Dig deeper into Java on developerWorks",
"IBM SmartCloud trial. No charge.",
"Special offers",
"Share this page:",
"Follow developerWorks:",
"Select a language:"
],
"site": "www.ibm.com",
"lastindexed": "20130520190956",
"keywords": "exception, exceptions, Groovy, Scala, Clojure, expressions, null, java.next, JVM languages, Neal Ford, dw_recommends, tttjca, tttosca",
"last_indexed_epoch": "1369076996305",
"title": "Java.next: Common ground in Groovy, Scala, and Clojure, Part 3",
"initial": "20130520190941",
"summaryText": " functional (Clojure and <B>Scala</B>) languages illustrates the evolution toward expressions. Groovy still has statements, which are based on Java syntax, but adds more expressions. <B>Scala</B> and Clojure use expressions...",
"content": "In the last installment , I covered innovative ways in which the Java.next languages reduce the ceremony and complexity that bedevil the Java language. In this installment, I show how these languages improve several Java sore spots: exceptions, statements versus expressions, and edge cases around null . Expressions One legacy that the Java language inherited from C is the distinction between programming statements and programming expressions . Examples of Java statements are code lines that use if or while , and ones that use void to declare methods that have no return value. Expressions, such as 1 + 2 , evaluate to a value. This split started in the earliest programming languages, such as Fortran, where the distinction was based on hardware considerations and a nascent understanding of programming-language design. It remained in many languages as an indicator of action (statement) versus evaluation (expression). But language designers independently and gradually realized that languages can consist entirely of expressions, ignoring the result when the outcome isn't of interest. Virtually all functional languages eliminate the distinction entirely, using only expressions. Groovy's if and ?: In the Java.next languages, the split between traditional imperative (Groovy) and functional (Clojure and Scala) languages illustrates the evolution toward expressions. Groovy still has statements, which are based on Java syntax, but adds more expressions. Scala and Clojure use expressions throughout. Inclusion of both statements and expressions adds syntactic clumsiness to languages. Consider the if statement in Groovy, inherited from Java. It has two versions, which are compared in Listing 1: the if statement for decisions, and the cryptic ternary operator ?: : Listing 1. Groovy's two if s def x = 5 def y = 0 if (x % 2 == 0) y = x * 2 else y = x - 1 println y // 4 y = x % 2 == 0 ? (x *= 2) : (x -= 1) println y // 4 In the if statement in Listing 1 , I must set the value of x as a side effect because the if statement has no return value. To perform the decision and assignment at the same time, you must use the ternary assignment, as in the second assignment in Listing 1 . Scala's expression-based if Scala eliminates the need for the ternary operator by allowing the if expression to handle both cases. You can use it just like the if statement in Java code (ignoring the return value) or use it in assignments, as in Listing 2: Listing 2. Scala's expression-based if val x = 5 val y = if (x % 2 == 0) x * 2 else x - 1 println(y) Scala, like the other two Java.next languages, doesn't require an explicit return statement for methods. In its absence, the last line of the method is the return value, emphasizing the expression-based nature of methods in these languages. As when you act and set values in Java and Groovy code, you can encapsulate each response as a code block, as in Listing 3, and include any desired side effects: Listing 3. Scala if + side effects val z = if (x % 2 == 0) { println(\"divisible by 2\") x * 2 } else { println(\"not divisible by 2; odd\") x - 1 } println(z) In Listing 3 , I print a status message for each case in addition to returning the newly calculated value. The order of the code lines within the block is important: The last line of the block represents the return value for that condition. Thus, you must exercise special care when you mix evaluation and side effects with expression-based if . Clojure's expressions and side effects Clojure also consists entirely of expressions but goes even further in differentiating side-effect code from evaluation. The Clojure version of the previous two examples is expressed in a let block, in Listing 4, which allows the definition of locally scoped variables: Listing 4. Clojure's expression-based if (let [x 5 y (if (= 0 (rem x 2)) (* x 2) (- x 1))] (println y)) In Listing 4 , I assign x a value of 5 , then create the expression with if to calculate the two conditions: (rem x 2) calls the remainder function, similar to the Java % operator, and compares the result to zero, checking for a zero remainder when you divide by 2. In Clojure's if expression, the first argument is the condition, the second the true branch, and the third is the optional else branch. The result of the if expression is assigned to y , which is then printed. Clojure also allows blocks (which can include side effects) for each condition but requires a wrapper such as (do ...) . The wrapper evaluates each expression in the block, by using the last line as the block's return value. Evaluating a condition and a side effect is illustrated in Listing 5: Listing 5. Explicit side effects in Clojure (let [x 5 a (if (= 0 (rem x 2)) (do (println \"divisible by 2\") (* x 2)) (do (println \"not divisible by 2; odd\") (- x 1)))] (println a)) In Listing 5 , I assign a the return value of the if expression. For each of the conditions, I create a (do ...) wrapper, allowing an arbitrary number of statements. The last line of the block is the return for the (do...) block, similar to the Scala example in Listing 3 . Ensure that the target return value is evaluated last. The use of (do...) blocks in this way is so common that many constructs in Clojure (such as (let []) ) already include implicit (do ...) blocks, eliminating their need in many cases. The contrast in treatment of expressions between Java/Groovy code and Scala/Clojure code is indicative of the general trend in programming languages to eliminate the unnecessary statement/expression dichotomy. Back to top Exceptions For me, the most \"seemed like a good idea at the time\" feature of Java programming was checked exceptions and the ability to broadcast (and enforce) exception awareness. In practice, it became a nightmare, forcing needless handling (and mishandling) of exceptions out of context. All the Java.next languages use the exception mechanism that is already built into the JVM, with syntax based on Java syntax and modified for their unique syntax. And they all eliminate checked exceptions, converting them into RuntimeExceptions when they're encountered during Java interop. Scala exhibits a couple of interesting behaviors in the translation of the Java exception-handling mechanism to work in its expression-based world. First, consider the fact that exceptions can be the return value of expressions, as illustrated in Listing 6: Listing 6. Exceptions as return values val quarter = if (n % 4 == 0) n / 4 else throw new RuntimeException(\"n must be quarterable\") In Listing 6 , I assign either one-fourth the value of n or an exception. If the exception triggers, the return value means nothing because the exception propagates before the return is evaluated. The legality of this assignment might seem odd, considering that Scala is a typed language. The Scala exception type is not a numeric type, and developers are unaccustomed to considering the return value of a throw expression. Scala solves this problem in an ingenious way, by using the special Nothing type as the return type of the throw . Any is at the top of the inheritance hierarchy in Scala (like Object in Java), meaning that all classes extend it. Conversely, Nothing lives at the bottom, making it an automatic subclass of all other classes. Thus, it is legal for the code in Listing 6 to compile: either it returns a number, or the exception triggers before a return value is set. The compiler reports no error because Nothing is a subclass of Int . Second, the finally block has interesting behaviors in an expression-based world. Scala's finally block works like the others functionally but exhibits a nuanced behavior around return values. Consider the code in Listing 7: Listing 7. Scala's return from finally def testReturn(): Int = try { return 1 } finally { return -1 } In Listing 7 , the overall return value is -1 . The finally block's return \"overrides\" the one from the body of the try statement. This surprising result occurs only when the finally block includes an explicit return statement; the implicit return is ignored, as illustrated in Listing 8: Listing 8. Scala's implicit return def testImplicitReturn(): Int = try { 1 } finally { -1 } In Listing 8 , the return value of the function is 1 , illustrating the intended use of the finally block as a place for cleaning up side effects rather than for resolving expressions. Clojure is also wholly expression-based. The return value of a (try ...) is always either: The last line of the try block in the absence of an exception The last line of the catch block that caught the exception Listing 9 shows the syntax for exceptions in Clojure: Listing 9. Clojure's (try...catch...finally) block (try (do-work) (do-more-work) (catch SomeException e (println \"Caught\" (.getMessage e)) \"exception message\") (finally (do-clean-up))) In Listing 9 , the return value of the happy path is the return from (do-more-work) . The Java.next languages take the best parts of the Java exception mechanism and discard the cumbersome parts. And, despite some implementation differences, they manage to incorporate exceptions into an expression-based perspective. Back to top Emptiness In a legendary conference presentation at QCon London in 2009, Tony Hoare called his invention of the \"null\" concept for ALGOL W — an experimental object-oriented language that he introduced in 1965 — \"a billion dollar mistake\" because of all the problems it caused in the programming languages that it influenced. The Java language itself suffers from edge cases around null , which the Java.next languages address. For example, a common idiom in Java programming guards against a NullPointerException before you attempt method invocation: if (obj != null) { obj.someMethod(); } Groovy has encapsulated this pattern into the safe navigation operator, ?. . It automatically does a null check of the left side and attempts only the method invocation if it is non-null; otherwise it returns null . obj?.someMethod(); def streetName = user?.address?.street Invocations of the safe navigation operator can also be nested. Groovy's closely related Elvis operator, ?: , shortens the Java ternary operator in the case of default values. For example, these lines of code are equivalent: def name = user.name ? user.name : \"Unknown\" //traditional ternary operator usage def name = user.name ?: \"Unknown\" // more-compact Elvis operator When the left side might already have a value (generally a default), the Elvis operator preserves it, otherwise setting a new value. The Elvis operator is a shorter, expression-leaning version of the ternary operator. Scala enhanced the concept of null and made it a class ( scala.Null ), along with a related class, scala.Nothing . Null and Nothing are at the bottom of the Scala class hierarchy. Null is a subclass of every reference class, and Nothing is a subclass of every other type. Scala offers an alternative to both null and exceptions to indicate absence of value. Many Scala operations on collections (such as get on a Map ) return an Option instance, which contains either of two parts (but never both): Some or None . The REPL interaction in Listing 10 shows an example: Listing 10. Scala's return of Option scala> val designers=Map(\"Java\" -> \"Gosling\", \"c\" -> \"K&R\", \"Pascal\" -> \"Wirth\") designers: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(Java -> Gosling, c -> K&R, Pascal -> Wirth) scala> designers get \"c\" res0: Option[java.lang.String] = Some(K&R) scala> designers get \"Scala\" res1: Option[java.lang.String] = None Notice in Listing 10 that the return from the successful get is an Option[java.lang.String] = Some(value) , whereas a failed lookup results in a None . A technique for unwrapping values from collections uses pattern matching, which is itself an expression that allows access and unpacking in a single terse expression: println(designers get \"Pascal\" match { case Some(s) => s; case None => \"?\"}) Option allows a better expression of emptiness than null alone, especially considering the syntactic support for its use. Back to top Conclusion In this installment, I delved into three problem areas in the Java language: expressions, exceptions, and null . Each of the Java.next languages addresses the pain points from Java, but each in its idiomatic way. The presence of expressions changes the idioms and options for seemingly unrelated concepts such as exceptions — further illustration that language features are highly coupled to one another. Java developers sometimes fall into the habit of thinking that inheritance is the only way to extend behavior. In the next installment, I show how the Java.next languages offer many more-powerful alternatives. Resources Learn Java.next: Common ground in Groovy, Scala, and Clojure, Part 1 (Neal Ford, developerWorks, March 2013): Address the inability to overload operators in the Java language with the Java.next languages: Groovy, Scala, and Clojure). Java.next: Common ground in Groovy, Scala, and Clojure, Part 2 (Neal Ford, developerWorks, April 2013): Reduce boilerplate and complexity with the syntactic conveniences offered by Java.next languages. Java.next: The Java.next languages (Neal Ford, developerWorks, January 2013): Explore the similarities and differences of three next-generation JVM languages (Groovy, Scala, and Clojure) in this overview of the Java.next languages and their benefits. Scala : Scala is a modern, functional language on the JVM. Clojure : Clojure is a modern, functional Lisp that runs on the JVM. Groovy : Groovy is a dynamic language for the JVM. Explore alternative languages for the Java platform (May 2012): Follow this knowledge path to investigate developerWorks content about various alternative JVM languages. Language designer's notebook (April 2010-Octover 2011): In this developerWorks series, Java Language Architect Brian Goetz explores some of the language design issues that presented challenges for the evolution of the Java language in Java SE 7, Java SE 8, and beyond. Functional thinking : Explore functional programming in Neal Ford's column series on developerWorks. More articles by this author (Neal Ford, developerWorks, June 2005-current): Learn about Groovy, Scala, Clojure, functional programming, architecture, design, Ruby, Eclipse, and other Java-related technologies. developerWorks Java technology zone : Find hundreds of articles about every aspect of Java programming. Get products and technologies Download IBM product evaluation versions and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®. Discuss Check out developerWorks blogs and get involved in the developerWorks community . About the author Neal Ford is Director, Software Architect, and Meme Wrangler at Thought Works, a global IT consultancy. He is also the designer and developer of applications, instructional materials, magazine articles, courseware, and video/DVD presentations, and he is the author or editor of books spanning a variety of technologies, including the most recent Presentation Patterns . He focuses on designing and building large-scale enterprise applications. He is also an internationally acclaimed speaker at developer conferences worldwide. Check out his website . Close [x] The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post . You may update your IBM account at any time. All information submitted is secure. Close [x] The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks. Please choose a display name between 3-31 characters . Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons. All information submitted is secure. Back to top",
"score": 2.2683775,
"summaryTitle": "Java.next: Common ground in Groovy, <B>Scala</B>, and Clojure, Part 3",
"type": "search",
"description": "The last of three installments about commonalities among Clojure, Scala, and Groovy investigates how these languages handle exceptions, expressions, and null -- all problem areas for the Java language. Each of the Java.next languages addresses the shortcomings of the Java language through a unique implementation that highlights that language's characteristics.",
"cities": "de",
"lang": "en",
"url": "http://www.ibm.com/developerworks/library/j-jn4/index.html",
"referrer": "t.co",
"aggregate_link": "http://bit.ly/10AnNDF",
"lastseen": "20130520190941",
"page": "http://www.ibm.com/developerworks/library/j-jn4/index.html"
},
{
"domain": "ticketweb.co.uk",
"initial_epoch": "1369040151000",
"h2": [
"WAR OF THE WORLDS BALL",
"Best available tickets",
"Your order"
],
"h3": [
"General Admission",
"Choose Tickets - how many tickets of each type would you like to purchase",
"Search tickets - let us suggest the best available seats or choose price & location yourself\""
],
"site": "www.ticketweb.co.uk",
"lastindexed": "20130520151008",
"keywords": "Checkout",
"last_indexed_epoch": "1369062608907",
"title": "WAR OF THE WORLDS BALL Tickets at Scala | Ticketweb",
"initial": "20130520085551",
"summaryText": "Close General Admission GBP 11.23-33.73 (inc. GBP 1.24-3.74 fees) Our prices include the ticket fee and all taxes. Delivery and Payment charge may be added on the Checkout Page.",
"content": "Close General Admission GBP 11.23-33.73 (inc. GBP 1.24-3.74 fees) Our prices include the ticket fee and all taxes. Delivery and Payment charge may be added on the Checkout Page.",
"score": 1.8627386,
"summaryTitle": "WAR OF THE WORLDS BALL",
"type": "search",
"description": "Buy tickets for WAR OF THE WORLDS BALL at Scala with TicketWeb",
"cities": "gb",
"lang": "en",
"url": "https://www.ticketweb.co.uk/event/war-of-the-worlds-ball-tickets/42883?camefrom=wmmonprom",
"referrer": [
"facebook.com",
"direct"
],
"aggregate_link": "http://bit.ly/13FiGY4",
"lastseen": "20130520150952",
"page": "https://www.ticketweb.co.uk/event/war-of-the-worlds-ball-tickets/42883",
"ogtitle": "WAR OF THE WORLDS BALL"
},
{
"domain": "wordpress.com",
"initial_epoch": "1368724059000",
"h2": [
"First Steps with Titan using Rexster and Scala",
"Titan Server",
"Rexster Console",
"RexPro in Scala",
"EC2",
"Next Steps",
"Conclusion"
],
"h3": [
"Like this:",
"Leave a Reply Cancel reply",
"Search this Blog",
"Top Posts",
"Recent Posts",
"Tags",
"Links",
"Twitter",
"Follow “Zach's Blog”"
],
"site": "zcox.wordpress.com",
"lastindexed": "20130520082258",
"last_indexed_epoch": "1369038178134",
"title": "First Steps with Titan using Rexster and Scala | Zach's Blog",
"initial": "20130516170739",
"summaryText": " main point is that the database and the application exist on different servers. Since <B>Scala</B> is the language of choice at Pongr , we’ll also be writing code in <B>Scala</B> and managing the project with sbt...",
"content": "Titan is a distributed graph database that runs on top of Cassandra or HBase to achieve both massive data scale and fast graph traversal queries . There are benefits to Titan on only a single server and it seamlessly scales up from there . It’s great to know that Titan scales but when first starting out you may just need it on a single server, either for local development or powering a small production application. However, there are so many Titan deployment options and associated tools & technologies that it can be difficult to know where to get started. This post assumes the standard architecture for a web application: a database running on a server that is remote from where the application runs. Therefore the application needs to communicate with the database over the network. The application could be a web site, a RESTful web service, or any of a variety of different services. The main point is that the database and the application exist on different servers. Since Scala is the language of choice at Pongr , we’ll also be writing code in Scala and managing the project with sbt . In addition to the application communicating with the database, we would also like to have interactive command-line access to send ad-hoc commands and queries to the database. This is incredibly useful to test out queries and make sure the application is storing the correct data. We will accomplish the goals above using the following approach: Titan Server : Titan + Cassandra + Rexster as the database server Rexster Console – shell access to remote Titan server via Gremlin RexPro Java  client library – send Gremlin queries to remote Titan server from Java (or Scala) The example application and more details are available at  https://github.com/zcox/rexster-titan-scala . Titan Server Titan Server provides a very convenient all-in-one package to get Titan up-and-running quickly. Cassandra is used as the underlying data storage. Titan provides graph database functionality on top of Cassandra. Rexster exposes the Titan graph to remote applications via the network. All three of these systems run within the same JVM so calls between them are performant. These simple commands download Titan Server 0.3.1 and fire it up: wget http://s3.thinkaurelius.com/downloads/titan/titan-cassandra-0.3.1.zip unzip titan-cassandra-0.3.1.zip cd titan-cassandra-0.3.1 bin/titan.sh config/titan-server-rexster.xml config/titan-server-cassandra.properties When everything has started you should notice a process bound to port 8184. This is the RexPro port and it is ready to receive incoming connections. The provided titan-server-rexster.xml and titan-server-cassandra.properties files contain good basic defaults, but would require modifications for production deployments. You would also want to run titan.sh from something like Upstart  as a daemon. Rexster Console Next we use the Rexster Console to quickly test out our new Titan server and create a simple graph in it. Here are commands to download and start the console: wget http://tinkerpop.com/downloads/rexster/rexster-console-2.3.0.zip unzip rexster-console-2.3.0.zip cd rexster-console-2.3.0 bin/rexster-console.sh Inside the shell, you write Gremlin queries to interact with the graph in Titan, much as you would write SQL to interact with a MySQL database via the MySQL command-line client. Let’s create 3 nodes connected by 2 edges. (l_(l (_______( 0 0 ( (-Y-) l l-----l l l l,, l l,, opening session [127.0.0.1:8184] ?h for help rexster[groovy]> g = rexster.getGraph(\"graph\") ==>titangraph[embeddedcassandra:null] rexster[groovy]> v1 = g.addVertex([name:\"Zach\"]) ==>v[4] rexster[groovy]> v2 = g.addVertex([name:\"Scala\"]) ==>v[8] rexster[groovy]> e1 = g.addEdge(v1, v2, \"likes\", [since: 2009]) ==>e[n-4-2F0LaTPQAS][4-likes->8] rexster[groovy]> v3 = g.addVertex([name:\"NOS\"]) ==>v[12] rexster[groovy]> e2 = g.addEdge(v1,v3,\"likes\",[since:2012]) ==>e[z-4-2F0LaTPQAS][4-likes->12] rexster[groovy]> g.commit() ==>null rexster[groovy]> g.V.name ==>Zach ==>Scala ==>NOS rexster[groovy]> g.V('name','Zach').out('likes').name ==>Scala ==>NOS rexster[groovy]> ?q closing session with Rexster [ip-10-152-185-66.ec2.internal:8184]--> done Note that after modifying the graph we need to commit the transaction, so our changes are visible to other clients. RexPro in Scala Now that we have some simple data in our remote Titan database, let’s write some Scala code to query it. The first step is to add the rexster-protocol dependency to our build.sbt file: \"com.tinkerpop.rexster\" % \"rexster-protocol\" % \"2.3.0\" Now we can use the RexsterClientFactory to obtain a RexsterClient instance, and use that to send Gremlin queries to Titan : import com.tinkerpop.rexster.client.RexsterClientFactory val client = RexsterClientFactory.open(\"localhost\", \"graph\") val names: Seq[String] = client.execute(\"g.V.name\").toSeq debug(\"%d names: %s\" format (names.size, names.mkString(\"[\", \",\", \"]\"))) val zachLikes: Seq[String] = client.execute(\"g.V('name',name).out('likes').name\", Map(\"name\" -> \"Zach\")).toSeq debug(\"Zach likes %d things: %s\" format (zachLikes.size, zachLikes.mkString(\"[\", \",\", \"]\"))) client.close() Note that the raw Gremlin queries are defined in Strings. This may seem similar to old school JDBC but is currently the way to do things using RexPro on the JVM. Rexster does provide a way to write code using the Gremlin API directly, called Extensions . An Extension runs on the Titan/Rexster server, so it has no remote communication with Titan. The Extension is then available to client-side code via Rexster. There are also several “Object-Graph Mapper” libraries available such as Bulbs and Thunderdome that allow you to write client-side code at a higher-level than Gremlin queries in Strings. I’d really like to experiment with such an approach using Scala, and will definitely write a follow-up blog post with more details and options for client-side use of Rexster. Also note that the Scala compiler needs a few hints as to how to handle the type returned from execute(). This is common when the Java and Scala type systems collide, and would best be encapsulated in a Scala RexsterClient adapter. You can run the example app and see results of the queries: $ sbt run [info] Set current project to rexster-titan-scala (in build file:/home/zcox/dev/rexster-titan-scala/) [info] Running com.pongr.Main 2013-05-14 16:54:53,293 INFO c.t.r.client.RexsterClientFactory - Create RexsterClient instance: [hostname=localhost graph-name=graph port=8184 timeout-connection-ms=8000 timeout-write-ms=4000 timeout-read-ms=16000 max-async-write-queue-size=512000 message-retry-count=16 message-retry-wait-ms=50 language=groovy graph-obj-name=g transaction=true channel=2] 2013-05-14 16:54:53,925 DEBUG com.pongr.Main$ - 3 names: [Zach,Scala,NOS] 2013-05-14 16:54:54,004 DEBUG com.pongr.Main$ - Zach likes 2 things: [Scala,NOS] [success] Total time: 4 s, completed May 14, 2013 4:54:54 PM EC2 While the above walkthrough ran everything locally, this also works remotely on two separate EC2 instances using a few modifications to support the app and Titan on different servers: Make sure the server instance has port 8184 open to the client instance Titan Server: use private IP as  in titan-server-rexster.xml Rexster Console: bin/rexster-console.sh -rh [internal-hostname of titan-server] Scala code: Replace localhost in src/main/scala/main.scala with internal-hostname of titan-server Next Steps One of Titan’s major features is vertex-centric indexes , so we would definitely want to set those up either via the Rexster console or the RexPro client. Titan also supports external indexes which would also be very valuable to many applications. Since Titan scales out for high-availability and data size, it would be useful to know how that affects both Rexster Console as well as the RexPro client in application code. From an operations perspective, the stock Titan Server configs need some adjustment for production use. For example, by default the data is stored in /tmp, which you would definitely want to relocate, perhaps to a mounted EBS volume. Automated, periodic backups to S3 would also be advised, as would a proper Upstart script and perhaps a Titan Server Debian package. Conclusion Hopefully this blog post has shown how to easily get started using a remote Titan server both from an interactive shell as well as application code in Scala. We’ve only scratched the surface though, so be sure to read all of the linked documentation. About these ads",
"score": 1.8030281,
"summaryTitle": "First Steps with Titan using Rexster and <B>Scala</B>",
"type": "search",
"description": "Just another WordPress.com weblog (by Zach Cox)",
"cities": "us",
"lang": "en",
"url": "http://zcox.wordpress.com/2013/05/15/first-steps-with-titan-using-rexster-and-scala/",
"referrer": [
"t.co",
"direct",
"feedly.com",
"iconfactory.com"
],
"aggregate_link": "http://bit.ly/14sWM95",
"lastseen": "20130520082243",
"page": "http://zcox.wordpress.com/2013/05/15/first-steps-with-titan-using-rexster-and-scala/",
"ogtitle": "First Steps with Titan using Rexster and Scala"
},
{
"domain": "typepad.com",
"initial_epoch": "1369070779000",
"h2": [
"I'm a young American woman in Milan...and you're not. I go to La Scala a lot...and you don't.",
"May 20, 2013",
"About Opera Chic",
"Twitter",
"Archives",
"Categories",
"Search"
],
"h3": [
"Welcome Back, Jimmy!",
"Comments"
],
"site": "operachic.typepad.com",
"lastindexed": "20130520190919",
"last_indexed_epoch": "1369076959797",
"title": "Opera Chic: Welcome Back, Jimmy!",
"initial": "20130520172619",
"summaryText": "How do you get to Carnegie Hall? James Levine slayed the punchline and showed that nothing but iron will gets you onto that historic NYC stage. Last night , the American conductor, in a motorized wheelchair, broke his 2+ year performance absence with",
"content": "How do you get to Carnegie Hall? James Levine slayed the punchline and showed that nothing but iron will gets you onto that historic NYC stage. Last night , the American conductor, in a motorized wheelchair, broke his 2+ year performance absence with a comeback concert of Wagner, Beethoven and Schubert accompanied by the inexhaustible Russian pianist Evgeny Kissin . Bernheimer for the FT here .",
"score": 1.4174564,
"summaryTitle": "Opera Chic",
"type": "search",
"description": "How do you get to Carnegie Hall? James Levine slayed the punchline and showed that nothing but iron will gets...",
"cities": "null",
"lang": "en",
"url": "http://operachic.typepad.com/opera_chic/2013/05/welcome-back-jimmy.html",
"referrer": [
"t.co",
"typepad.com",
"direct"
],
"aggregate_link": "http://bit.ly/17UCTMT",
"lastseen": "20130520190905",
"page": "http://operachic.typepad.com/opera_chic/2013/05/welcome-back-jimmy.html",
"ogtitle": "Opera Chic: Welcome Back, Jimmy!"
},
{
"domain": "scala-london.co.uk",
"initial_epoch": "1369043469000",
"site": "www.scala-london.co.uk",
"lastindexed": "20130520095204",
"keywords": "scala, london, venue, club, live, music, hire, party, parties, corporate events, north, kings cross, king's cross, islington, camden, popstarz,",
"last_indexed_epoch": "1369043524764",
"title": "Scala London | Event",
"initial": "20130520095109",
"summaryText": "Thursday 10 October 2013 Kililive.com present BO NINGEN Plus special guests Time: 7.30pm until 11pm Admission: £10 in advance. Age 16+ ID required. Tickets: Onsale Friday 10th May from 9am via www.ticketweb.co.uk 08444 771 000 or <B>Scala</B> box office",
"content": "Thursday 10 October 2013 Kililive.com present BO NINGEN Plus special guests Time: 7.30pm until 11pm Admission: £10 in advance. Age 16+ ID required. Tickets: Onsale Friday 10th May from 9am via www.ticketweb.co.uk 08444 771 000 or Scala box office between 10am and 6pm Mon-Fri for ticket purchase (not collection) Go back",
"score": 1.3600172,
"summaryTitle": "<B>Scala</B> London | Event",
"type": "search",
"description": "Scala is London's alternative venue for live music, clubs, art, film, and corporate events.",
"cities": "null",
"lang": "en",
"url": "http://www.scala-london.co.uk/scala/event.php?id=2105",
"referrer": "facebook.com",
"aggregate_link": "http://bit.ly/15EuUTT",
"lastseen": "20130520095109",
"page": "http://www.scala-london.co.uk/scala/event.php"
},
{
"domain": "celebuzz.com",
"initial_epoch": "1366762003000",
"h2": "Lunch with Larsa",
"h3": "Photos From The E! Upfronts!",
"site": "kimkardashian.celebuzz.com",
"lastindexed": "20130520191254",
"keywords": [
"frankie payne,larsa pippen",
"Lunch with Larsa , Frankie Payne, Larsa Pippen"
],
"last_indexed_epoch": "1369077174940",
"title": "Lunch with Larsa - Kim Kardashian: Official website",
"initial": "20130424000643",
"summaryText": "Last week one of my closest friends, Larsa, was in town! I took her and her friends to La <B>Scala</B>! It was so much fun spending time and catching up! After lunch I met up with Bruce to go to the ear doctor. I am loving these braids right now! Frankie",
"content": "Last week one of my closest friends, Larsa, was in town! I took her and her friends to La Scala! It was so much fun spending time and catching up! After lunch I met up with Bruce to go to the ear doctor. I am loving these braids right now! Frankie Payne did my hair and I am just obsessed! Style Snapshot: I’m wearing J Brand jeans, a navy Carine Gilson camisole, a navy Stella McCartney blazer, and Casadei Heels.",
"score": 1.3475872,
"summaryTitle": "Lunch with Larsa ",
"type": "search",
"description": [
"Last week one of my closest friends, Larsa, was in town! I took her and her friends to La Scala! It was so much fun spending time and catching up! After",
"Last week one of my closest friends, Larsa, was in town! I took her and her friends to La Scala! It was so much fun spending time and catching up! After"
],
"cities": "us",
"lang": "en",
"url": "http://kimkardashian.celebuzz.com/2013/04/23/lunch-with-larsa/",
"referrer": [
"msn.com",
"jokerjokes.me",
"facebridge.net",
"kataweb.it",
"twittergadget.com",
"gecce.com",
"direct",
"galacticheadquarters.com",
"twitterrific.com",
"kimkardashianfrance.net",
"tweetlist.com",
"yandex.ru",
"peoplestylewatch.com",
"daum.net",
"bigmir.net",
"x17online.com",
"cre8.ru",
"netvibes.com",
"twitter.com",
"t.co",
"bit.ly",
"facebook.com",
"gala.de",
"dabr.co.uk",
"hollywoodpq.com",
"kanguru.pt",
"noticel.com",
"writelonger.com",
"flup.in",
"aol.com",
"closermag.fr",
"pulsonline.rs",
"7cars.org",
"celebritytweet.com",
"yahoo.com",
"iconfactory.com",
"telkomsa.net",
"bluecoat.com",
"kicaumedia.com",
"people.com",
"shopyourway.com",
"tuikk.net",
"hootsuite.com",
"ultwimate.com",
"tweetwood.com"
],
"aggregate_link": "http://bit.ly/15Hwx2k",
"lastseen": "20130520191237",
"page": "http://kimkardashian.celebuzz.com/2013/04/23/lunch-with-larsa/",
"ogtitle": "Lunch with Larsa "
}
]
},
"status_txt": "OK"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment