Java officially lags C

2 views
Skip to first unread message

joel.neely

unread,
Sep 1, 2009, 8:19:00 AM9/1/09
to The Java Posse
According to coverage at http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/10
, Snow Leopard, the latest version of Mac OS X, added "blocks" to C.
The article illustrates this new language construct with the by-now
canonical ARM and home-grown-control-structure examples.

Hey, Java! Closures to the left of me [JRuby, Scala, etc.], blocks to
the right [C on OS X], here I am, stuck in the middle with you!

Roel Spilker

unread,
Sep 1, 2009, 8:53:36 AM9/1/09
to The Java Posse
For ARM-blocks you can have a look at the @Cleanup annotation of
Lombok and have ARM-blocks for Java right now!

The following code will close both streams correctly after they run
out of scope.

import lombok.Cleanup;
import java.io.*;

public class CleanupExample {
public static void main(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
}

See http://projectlombok.org/features/Cleanup.html for more
information

On Sep 1, 2:19 pm, "joel.neely" <joel.ne...@gmail.com> wrote:
> According to coverage athttp://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/10

Casper Bang

unread,
Sep 1, 2009, 9:10:02 AM9/1/09
to The Java Posse
The neat thing about this is that we do not have to wait until the
Java API has been retrofitted with the Disposable interface. However,
you won't get the scope limitation benefits (the in and out variable
is scoped the whole method). I kind of wish we could use annotations
on blocks, so this would be possible instead:

@Cleanup{
InputStream in = new FileInputStream( ... );
// Do something...
}

@Cleanup{
InputStream in = new FileInputStream( ... );
// Do something else...
}

/Casper

On 1 Sep., 14:53, Roel Spilker <r.spil...@gmail.com> wrote:
> For ARM-blocks you can have a look at the @Cleanup annotation of
> Lombok and have ARM-blocks for Java right now!
>
> The following code will close both streams correctly after they run
> out of scope.
>
> import lombok.Cleanup;
> import java.io.*;
>
> public class CleanupExample {
>         public static void main(String[] args) throws IOException {
>                 @Cleanup InputStream in = new FileInputStream(args[0]);
>                 @Cleanup OutputStream out = new FileOutputStream(args[1]);
>                 byte[] b = new byte[10000];
>                 while (true) {
>                         int r = in.read(b);
>                         if (r == -1) break;
>                         out.write(b, 0, r);
>                 }
>         }
>
> }
>
> Seehttp://projectlombok.org/features/Cleanup.htmlfor more

Roel Spilker

unread,
Sep 1, 2009, 9:47:18 AM9/1/09
to The Java Posse
Caster, that is not entirely correct. The "close" methode (actually,
close is just the default, you can specify an other method name if you
want) will be called when the variable goes out of scope.
Unfortunately, java does not allow an annotation on a code block. So
an equivalent programm would be:

{
@Cleanup InputStream in = new FileInputStream(...);
// Do something else...

Casper Bang

unread,
Sep 1, 2009, 10:10:35 AM9/1/09
to The Java Posse
I think you misunderstood Roel. I am aware of the method name argument
override, I was merely exploring the different implementations and
implications of these two ARM blocks. The JDK7 version would have to
rely on a new interface Disposable being added to the libraries, as
the abomination known as checked exceptions (IOException) once again
gets in the way of simply using the existing Closable. Lombok couldn't
care less what it's closing and could in fact be used as a C++
deconstructor. Correct?

/Casper

Roel Spilker

unread,
Sep 1, 2009, 10:17:54 AM9/1/09
to The Java Posse
Casper,

You are correct. I just wanted the other readers to know that it is
not limited to "close". It is however limited to no-args methods.

Roel

Jess Holle

unread,
Sep 1, 2009, 10:31:48 AM9/1/09
to java...@googlegroups.com
I actually prefer @Cleanup to the JDK 7 proposal in that it presumably just cleans up at the end of the variable's scope ala C++.

If you need ordering amongst several @Cleanup variables, then you can always introduce {...} scoping, right?  If so, then I'd rather introduce such things only as needed rather than the JDK 7 proposal's approach.

Reinier Zwitserloot

unread,
Sep 1, 2009, 1:47:48 PM9/1/09
to The Java Posse
Yes, you can scope to your hearts content with {} blocks. For those
not aware of this:

There's a rarely used feature of the java language: separate blocks.

You can put { (statements) } anywhere in java code where a statement
is legal. Like any other occurrence of {} to delimit code, any
variable declarations inside the {} are not visible outside the
brackets. So, this:

public void test() {
int foo = 1;
{
int bar = foo + 2;
}
//MARK
}

is legal, and 'bar' will not be visible at the mark. Because of this
feature, @Cleanup is what it is; if you want an explicit close point,
then use a block. In practice, a decent amount of resources you may
want to @Cleanup require try/catch blocks, which are of course also
their own scope:

try {
@Cleanup InputStream in = new FileInputStream(path);
} catch ( IOException e ) {
throw new DatabaseAccessException(e);
}

After all, the act of creating a resource tends to throw the same
kinds of exceptions as using the resource.

Funny thing, this @Cleanup thing. I never considered this style of ARM
until forced into it by lombok's particular limitations (Specifically:
it needs code that passes the tokenizer and tree maker before lombok
can run its transformations), and then it turns out it's in many ways
superior to the existing proposal. I don't think coin is going to go
this route though, it's a bit late for such a drastic change.

Casper Bang

unread,
Sep 1, 2009, 2:12:12 PM9/1/09
to The Java Posse
True, but I don't think many are aware of this. The JDK7 proposal by
Joshua Bloch specifically adds the multi-scoping aspect over the
existing C# implementation, which only allows multi-scoping of the
same type.

Constructs that minimizes variable leakage into scope space (temporary
variables) appeals somewhat to me, something Lombok can't possible
address without an ElementType.TYPE_BLOCK.

I assume this is also a major reason why certain well known people on
the Coin mailing-list claim this should be handled in the language
rather than by annotations. There's a profound fear of the misuse of
annotations, though personally I consider annotation DSL burial (JPA)
way more abusive than say Lombok.

/Casper

Jess Holle

unread,
Sep 1, 2009, 8:16:29 PM9/1/09
to java...@googlegroups.com
Casper Bang wrote:
True, but I don't think many are aware of this.
Hmm.... I've used {...} liberally for scoping in Java and C++ since I first used C++.  It's one reason I consider C unusable even compared to C++'s and despite C++'s sins.

The JDK7 proposal by
Joshua Bloch specifically adds the multi-scoping aspect over the
existing C# implementation, which only allows multi-scoping of the
same type.

Constructs that minimizes variable leakage into scope space (temporary
variables) appeals somewhat to me, something Lombok can't possible
address without an ElementType.TYPE_BLOCK.

I assume this is also a major reason why certain well known people on
the Coin mailing-list claim this should be handled in the language
rather than by annotations. There's a profound fear of the misuse of
annotations, though personally I consider annotation DSL burial (JPA)
way more abusive than say Lombok.
  
Annotations whiich produce language-like effects, i.e. changes in the byte code (not just metadata) for the class in question is a slippery slope.  The extreme cases would generally seem to be a bad thing -- though it is the only way we have to (relatively) cheaply get something like Lombok right now.

There's a huge aversion to new keywords at this point and something like
try InputStream in = new FileInputStream(path);
just doesn't look right.  Something like
auto InputStream in = new FileInputStream(path);
might, but it's still a new keyword.

Overall, however, the point is that to eliminate the need for {...} bracketing where it is otherwise unnecessary, e.g.:
auto Foo foo = new Foo();
auto Bar bar = new Bar();
auto Baz baz = new Baz();
// code using vars here ...
rather than (in the one true bracing style):
try ( Foo foo = new Foo() )
{
  try ( Bar bar = new Bar() )
  {
    try ( Baz baz = new Baz() )
    {
      // code using vars here ...
    }
  }
}
or even
try ( Foo foo = new Foo() ) {
  try ( Bar bar = new Bar() ) {
    try ( Baz baz = new Baz() ) {
      // code using vars here ...
    }
  }
}
--
Jess Holle

Mark Derricutt

unread,
Sep 1, 2009, 8:44:45 PM9/1/09
to java...@googlegroups.com
I've always been intrigued by these blocks we have in java, what does javac actually generate for them?  I'd always hoped that the closures proposals might just start small and make these blocks a first class citizen.

From:

public void test() {
   int foo = 1;
   {
       int bar = foo + 2;
   }
   //MARK
}

to:

public void test() {
   int foo = 1;
   Method foobar = {

       int bar = foo + 2;
   }

   foobar.invoke(null);
   //MARK
}

*sigh* I want my closures and mixins.

--
Pull me down under...

Sent from Auckland, Auk, New Zealand

Marcelo Fukushima

unread,
Sep 1, 2009, 9:12:26 PM9/1/09
to java...@googlegroups.com
for local variables, javac actually does almost nothin:it only frees
that local variable slot for a future local variable

theres a nice puzzle about that in the java specialists newsletter:
http://www.javaspecialists.eu/archive/Issue173.html

of course youre not suppose to know its about local variables and
javac before seeing the puzzle...
--
http://mapsdev.blogspot.com/
Marcelo Takeshi Fukushima

Casper Bang

unread,
Sep 1, 2009, 10:40:33 PM9/1/09
to The Java Posse
Don't know what happens underneath, but they appear to be parsed by
the production rule Block -> {Statement*} and have the Tree node
associated with a com.sun.tools.javac.code.Scope hashtable that's
special in that they can be nested. That would make sense I guess,
going the other way, a member-wide variable is also contained in a
Scope with nested Scopes (methods). That's why I think it would be
possible to allow an annotation type on a block.

There are more things than just ARM you could want to do.
Transactions, logging, timing etc. As Stephen Colebourne has hinted at
in the past, one could even use it for DSL's:

@DSL(lang="jpql", variant="hibernate"){
SELECT FROM foobar;
}

That would take care of the need of multi-line strings for most cases.

/Casper
> > On Wed, Sep 2, 2009 at 5:47 AM, Reinier Zwitserloot <reini...@gmail.com>

James Iry

unread,
Sep 1, 2009, 10:53:26 PM9/1/09
to java...@googlegroups.com
On Tue, Sep 1, 2009 at 5:44 PM, Mark Derricutt <ma...@talios.com> wrote:
I've always been intrigued by these blocks we have in java, what does javac actually generate for them?  

Not much.   It just reuses slots. But don't take my word for it

~/test$ cat Test.java
public class Test {

  public void test() {
    int foo = 1;
    {
      int bar = foo + 2;
      System.out.println("inner bar = " + bar);
    }
    int bar = foo + 3;
    System.out.println("outer bar = " + bar);
  }
}
~/test$ javac Test.java
~/test$ javap -c -private Test
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
  Code:
   0:    aload_0
   1:    invokespecial    #1; //Method java/lang/Object."<init>":()V
   4:    return

public void test();
  Code:
   0:    iconst_1
   1:    istore_1
   2:    iload_1
   3:    iconst_2
   4:    iadd
   5:    istore_2
   6:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   9:    new    #3; //class java/lang/StringBuilder
   12:    dup
   13:    invokespecial    #4; //Method java/lang/StringBuilder."<init>":()V
   16:    ldc    #5; //String inner bar =
   18:    invokevirtual    #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   21:    iload_2
   22:    invokevirtual    #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
   25:    invokevirtual    #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   28:    invokevirtual    #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   31:    iload_1
   32:    iconst_3
   33:    iadd
   34:    istore_2
   35:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   38:    new    #3; //class java/lang/StringBuilder
   41:    dup
   42:    invokespecial    #4; //Method java/lang/StringBuilder."<init>":()V
   45:    ldc    #10; //String outer bar =
   47:    invokevirtual    #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   50:    iload_2
   51:    invokevirtual    #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
   54:    invokevirtual    #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   57:    invokevirtual    #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   60:    return

}

 
The instructions istore_2 and iload_2 each appear twice (the stores happen after the adds, the loads appear before the string builds).  That's javac reusing the same slot in the local variable table since the inner "bar" is no longer needed when it encounters the outer "bar."  slot 1 is tied to foo for the enitre method.  const 1 is 1, const 2 is 2, and const 3 is 3.

 
I'd always hoped that the closures proposals might just start small and make these blocks a first class citizen.


Closures are more complicated than simple blocks.  Because closures capture variables into potentially long lived objects that transcend normal stack behavior, mutable variables need to be heap allocated.  That, by the way, is why Java's existing sorta-closures (instances of anonymous inner classes) are only allowed to capture final variables.  In Java 1.2 the largest users of Java were C++ programmers who were mortified at the thought of Java silently introducing extra heap allocation without explicit "new".  http://madbean.com/2003/mb2003-49/

Reinier Zwitserloot

unread,
Sep 2, 2009, 1:15:29 PM9/2/09
to The Java Posse
No, A @DSL annotation isn't nearly enough to take care of arbitrary
DSLing, or arbitrary literals.

For example, let's try to use this for multi-line:

@DSL(lang="longString") {
""" I am a really really
really long string. I'm also going to contain a bracket: } because
I'm annoying like that."""
}


tell me how the compiler could possibly sort this out? The only way is
for the compiler to hand off the entire process of TOKENIZING this
stream to the DSL provider for 'longString', which is an entirely
different architecture - right now all java parsers do the fairly
usual thing of tokenizing the whole deal, then tree-izing the whole
thing, and only then starting the process of resolving 'DSL' into
"java.lang.DSL" or whatever you had in mind.


You'd have to create very specific rules about how the compiler can
find the end of the DSL string. I've thought about this and have not
been able to come up with a particularly sensible rule. The only one I
can think of is to stick to C-esque rules: strings are things in
double or single quotes, and use backslash internally for escapes, and
braces are supposed to be matched. However, these restrictions already
remove most other languages: You can't put python in there (multi-line
strings will screw up java's parser), you can't put regular
expressions in there (no rule enforcing matched quotes or braces). You
can't put XML in there (no rule enforcing matched braces or quotes).
No go.

Casper Bang

unread,
Sep 2, 2009, 1:39:28 PM9/2/09
to The Java Posse
> tell me how the compiler could possibly sort this out? The only way is
> for the compiler to hand off the entire process of TOKENIZING this
> stream to the DSL provider for 'longString', which is an entirely
> different architecture - right now all java parsers do the fairly
> usual thing of tokenizing the whole deal, then tree-izing the whole
> thing, and only then starting the process of resolving 'DSL' into
> "java.lang.DSL" or whatever you had in mind.

Oh sure, I should had mentioned explicitly how this obviously won't
work with a vanilla javac. Anyway here's the original post I was
referring: http://www.jroller.com/scolebourne/entry/enhancing_java_multi_lingual_blocks

> You'd have to create very specific rules about how the compiler can
> find the end of the DSL string. I've thought about this and have not
> been able to come up with a particularly sensible rule. The only one I
> can think of is to stick to C-esque rules: strings are things in
> double or single quotes, and use backslash internally for escapes, and
> braces are supposed to be matched. However, these restrictions already
> remove most other languages: You can't put python in there (multi-line
> strings will screw up java's parser), you can't put regular
> expressions in there (no rule enforcing matched quotes or braces). You
> can't put XML in there (no rule enforcing matched braces or quotes).
> No go.

Well it's not a trivial issue no, but this is how it work in Fan:
http://fandev.org/sidewalk/topic/438

/Casper

Jess Holle

unread,
Sep 2, 2009, 2:33:57 PM9/2/09
to java...@googlegroups.com
Hmm...

I've never really had an issue with simply doing

"My string is really really really really really really really really really " +
"really really really really really really really really really really really really " +
"really really really long."

The extra "'s and +'s are a non-problem in my book (IDE's help you with them as well...) -- at least compared to the many real problems that I encounter :-)

--
Jess Holle

Casper Bang

unread,
Sep 2, 2009, 3:19:34 PM9/2/09
to The Java Posse
The issue goes a little deeper than your simple use case though. The
Java enterprise world, due to the lack of expression trees, has to
work with many thousands lines of embedded DSL (JPQL/HQL/SQL etc.).
This poses several problems:

- How do you format/indent it?
- How do you copy-paste between database tool and IDE?
- How do you get help with the syntax?

By my experience, that is very much a real problem :

" select new com.somecompany.somexp.backend.model.ManagerInfoRecord("+
" c, b.itemNo, x )" +
" from SomeEntity x" +
" Join x.account a" +
" Join a.baseData b" +
" Join b.customer c "+
" where x.state <> com.somecompany.somexp.backend.entities.SomeEntity
$ReadingState.InValid " +
" and ( " +
" (" +
" x.someState = com.somecompany.somexp.backend.entities.SomeEntity
$someState.Valid " +
" and b.someData <> 'Y' " +
" )" +
" or x.someOtherState =
com.somecompany.somexp.backend.entities.SomeEntity
$someOtherState.Valid " +
" )" +
" and b.relatedEntity =:relatedEntity " +
" and x.someForeignRelation <>
com.somecompany.somexp.backend.entities.SomeEntity$EntityStateEnum.E
" ),

And that's just one small annotation query (obfuscated to protect the
innocent). Fun eh? :)

/Casper

On 2 Sep., 20:33, Jess Holle <je...@ptc.com> wrote:
> Hmm...
>
> I've never really had an issue with simply doing
>
> "My string is really really really really really really really really
> really " +
> "really really really really really really really really really really
> really really " +
> "really really really long."
>
> The extra "'s and +'s are a non-problem in my book (IDE's help you with
> them as well...) -- at least compared to the many /real /problems that I

Reinier Zwitserloot

unread,
Sep 2, 2009, 4:22:42 PM9/2/09
to The Java Posse
Casper: I don't think you grokked my point.

I'm saying it's impossible to build any java, vanilla or otherwise,
that can handle this. For the reasons I stated: You'd have to flip the
architecture upside down and resolve 'DSL' properly midway through
tokenizing it. Be aware that this automatically means that any error
caused by the DSL provider *HAS TO* stop the parsing right there on
the spot, no further error reporting for anything that follows the DSL
block. Tricks IDEs do to make a class file with whatever methods have
syntax errors in them replaced with dummies that throw exceptions
would be impossible.

You'd be giving up an awful lot.

Don't get me wrong, I love the idea, but I haven't seen a workable
proposal yet. I'm leaning towards the notion that it's impossible to
get right. Fan tries to use a sufficiently arcane separator (bar-
angle, so <| special code goes here |>), but if java uses the same
thing, then you can't embed fan in java. That's not a solution.

Here's a simplistic approach to something that might actually work:

1. identifier resolution is decoupled from the rest of the source file
for parsing. In other words, the parser will parse all import
statements, resolve them, and only then continue on its way.

2. blocks start with a hash, followed by a type identifier. This type
identifier is resolved only according to import statements; to make
this smooth, the definitions for how to handle these blocks MUST
ALWAYS be top level members, no exceptions. Now the parser does not
have to consider inner classes and such to resolve the name; the
process of checking the current package and all import statements
suffices.

3. The tokenizer will remember the character that followed the token
(e.g. the non-identifier character that immediately followed the last
identifier character in the DSL name, which can be a space, a quote, a
brace, whatever), and restuffs this back into the source view. The
tokenizer then hands the raw source (as a Reader or some such) off to
the .tokenize() method of the provider. The tokenizer MUST return any
object, and have consumed exactly up to (and including) the closing
element of the DSL block.

4. During compilation, the DSL block (which is an expression which can
have an arbitrary type, including void) is translated into a pure java
expression by calling the .parse() method of the DSL provider.

5. Exceptions during the tokenize phase result in the immediate end of
parsing that java source file, as javac will not know where to
continue. Exceptions during the parse method aren't nearly as drastic;
it just means there's an error in the DSL block and the block's
expression is of an unknown type - certainly not rocket science
compared to the advanced error recovery employed in many IDEs.

public interface DSLProvider<T> {
public T tokenize(SourceReader reader);
public String parse(T token, Context c);
}



some open issues are: What should 'parse' return - there's an argument
to be made for: 'bytecode', 'raw java source as a String', and 'a
JCExpression object (from javac's internal AST classes). Each has its
advantages and disadvantages.

Context is some useful construct that allows access to variables legal
in the current scope, the filer (for looking up types), and similar
things. A lot of this API already exists (annotation processor API).

Such a system could rather easily support a wide variety of stuff you
may wish to inject into java source files:

- String literals
- Regexp literals - the compiled regexp tree would be stored into the
class file.
- XML literals
- multiline and/or raw string literals.
- python - even including python's whitespace based delimiting as the
mechanism to delimit the block ITSELF, if you think that is a good
idea.
- Clojure, LISP, and other lisp dialects.
- just about every programming language in existence (incl. ruby,
Javascript, C, C#, C++, fortran, ada, and, sure, why not - APL).

The documentation should stress that the .tokenize() method really
should try its very best to return and not throw an exception.

hypothetical source:

int x = #python:
5 + 5
int thisIsJavaAgain;

String long = #long """This is a long string where \backslashes need
not be escaped""" + "this is parsed by javac again";
Pattern p = #regexp /[abc]d\s+(\d*)/i;

Presuming that the context object is sufficiently advanced, this
should also be possible, especially if you add a way to parse a java
snippet in that context:

private final Comparator<Integer> absoluteComparator = #closure
Comparator(Integer a, Integer b) { return Integer.compare(Math.abs(a),
Math.abs(b)); };


Of course, trying to include java inside such a block has the same
issue as javac's original problem: How does the closure DSL provider
know where the closure ends without being as complicated as javac's
tokenizer? Theoretically java itself could be implemented with this
scheme, and you could then start the snippet parser at the 'return'
statement, getting a tokenized object back, which, during your parse
phase, you can get parsed by calling on javac's own parse method.

The central point is this: You have to split tokenizing and parsing.
This is yet another instance where fan tries to take the easy way out.


On Sep 2, 7:39 pm, Casper Bang <casper.b...@gmail.com> wrote:
> > tell me how the compiler could possibly sort this out? The only way is
> > for the compiler to hand off the entire process of TOKENIZING this
> > stream to the DSL provider for 'longString', which is an entirely
> > different architecture - right now all java parsers do the fairly
> > usual thing of tokenizing the whole deal, then tree-izing the whole
> > thing, and only then starting the process of resolving 'DSL' into
> > "java.lang.DSL" or whatever you had in mind.
>
> Oh sure, I should had mentioned explicitly how this obviously won't
> work with a vanilla javac. Anyway here's the original post I was
> referring:http://www.jroller.com/scolebourne/entry/enhancing_java_multi_lingual...
>
> > You'd have to create very specific rules about how the compiler can
> > find the end of the DSL string. I've thought about this and have not
> > been able to come up with a particularly sensible rule. The only one I
> > can think of is to stick to C-esque rules: strings are things in
> > double or single quotes, and use backslash internally for escapes, and
> > braces are supposed to be matched. However, these restrictions already
> > remove most other languages: You can't put python in there (multi-line
> > strings will screw up java's parser), you can't put regular
> > expressions in there (no rule enforcing matched quotes or braces). You
> > can't put XML in there (no rule enforcing matched braces or quotes).
> > No go.
>

mbien

unread,
Sep 2, 2009, 5:44:40 PM9/2/09
to The Java Posse
Hi,
or just do it like html does it...

@DSL(lang="Brainfuck") {
/*
++++++++++[>+++++++>++++++++++>+++>
+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++
++++++++.>.+++.------.--------.>+.>.
*/
}

javac ignores the comment, preprocessors like projectlombok.org could
do whatever they want with the comment (convert to string, generate
code etc)..
(of course the escaping char issue remains...)

regards,
- - -
http://michael-bien.com

Jess Holle

unread,
Sep 2, 2009, 7:53:57 PM9/2/09
to java...@googlegroups.com
You don't embed this sort of thing. You use getResourceAsStream() and a
separate file along with MessageFormat or such to perform substitutions
of live data if need be.

Plain and simple.

This also allows the IDE to do easily appropriate things for a .sql file
or the like.

[In the XML sphere I'm all for sticking SVG, XSL FO, etc, directly
inside an XHTML document -- but this whole approach seems to be dying on
the vine there, even though the grammar is the same throughout all of
these.]

--
Jess Holle

Casper Bang

unread,
Sep 2, 2009, 8:16:59 PM9/2/09
to The Java Posse
Annotations are the recommended way however, as it facilitates
validation. If you use em.createQuery(...) everything is late-bound
and even less type checked than using a namedQuery. For SQL though,
you are absolutely right but sadly SQL is no longer considered trendy.

/Casper

Frederic Simon

unread,
Sep 3, 2009, 3:27:52 AM9/3/09
to java...@googlegroups.com
I use to always put my SQL code in specific files, because I came from ugly Oracle SQL preprocessor where SQL and code where mixed like hell (JSP files are the same BTW).
But, today I prefer Named Queries and/or JDBC 4.
I use to declare my ORM mapping and my Depency Injection in a separate XML file :)
Now I used JPA and JaCaDI (JSR-299 + JSR-330)

Having the SQL query above the method that will execute is a HUGE benefit:
@SQL("select id from datastore where length > :threshold")
Collection<Long> getIdsAbove(long threshold);

Clear, easy to debug/modify/refactor and especially extremely clear usage of what the method is doing.

It's the same for ORM and DI using Annotations vs. XML.

It's hard to have a good balance when mixing languages in the same file, but when done right it's always a winner.
Clean injection of DSL is the good way to go.
--
JFrog Ltd
5 Habonim st., P.O.Box 8187
Netanya, Israel 42504.
Tel: +972 9 8941444    
Fax: +972 9 8659977
http://www.jfrog.org/
http://freddy33.blogspot.com/
http://nothingisinfinite.blogspot.com/

B Smith-Mannschott

unread,
Sep 3, 2009, 4:36:04 AM9/3/09
to java...@googlegroups.com
On Thu, Sep 3, 2009 at 01:53, Jess Holle<je...@ptc.com> wrote:
>
> You don't embed this sort of thing.  You use getResourceAsStream() and a
> separate file along with MessageFormat or such to perform substitutions
> of live data if need be.
>
> Plain and simple.

Yup. Good idea. So you've now maximally separated definition from
usage, so that when editing one you lose the context of the other. For
even better effect, use a maven project layout and have your .sql file
buried under src/main/resouces while the java code that loads it,
substitutes in variables and calls the data base is in src/main/java.
For extra masochism you could embed your SQL fragments in a nest of
angle brackets.

Sorry, that was harsh, but there is a trade-off being made here which
should be considered.

*waaaaay* back in the day, I rewrote a tool to generate Java classes
specific to our business object framework from UML diagrams in
Rational Rose (which had a truly demented almost-clone of VBA
embedded).

The original tool was a hideous sprawl of mile-long print statements
containing a heady mixture of literal string fragments and (mostly
global) variables. It was unreadable.

The first thing I did was write a *very simple* templating system, so
I could put the java code fragments into templates containing named
"substitution points" (i.e. variables, think "${classname}"). Then the
code generator would load up the template by name, perform
substitutions on it by providing name/value pairs and then finally
output the result.

I quickly found that this was tedious, because the code was referring
to names (of substitution points and templates) that I wasn't seeing
while coding. I finally ended just embedding the templates in the
program as comments. (The first thing the script did when starting up,
was load the templates by reading through its own source. Sick, but it
worked well.) That way they were declared close to their point of use
and one could easily refer back and forth while developing and
modifying the program.

Though unconventional, this solution turned out to be a
maintainability win, almost entirely due to the fact that I was able
to keep use and declaration close to each other.

> This also allows the IDE to do easily appropriate things for a .sql file
> or the like.
>
> [In the XML sphere I'm all for sticking SVG, XSL FO, etc, directly
> inside an XHTML document -- but this whole approach seems to be dying on
> the vine there, even though the grammar is the same throughout all of
> these.]

Yea, you'd think that the XML vocabularies out there would be a
natural fit for some kind of literate programming approach, like an
XHTML document which both explains and embeds an XSD along with
tooling to generate human-readable XHTML and machine-readable XSD from
the combined doc.

But, sadly, not so much of that going on.

// Ben

Reply all
Reply to author
Forward
0 new messages