You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-dev@db.apache.org by "David Van Couvering (JIRA)" <de...@db.apache.org> on 2005/04/27 19:49:33 UTC

[jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

     [ http://issues.apache.org/jira/browse/DERBY-214?page=comments#action_63912 ]
     
David Van Couvering commented on DERBY-214:
-------------------------------------------

Hi, Kathey.  I think I can work on this.  Is it OK for NetworkServerControl to call System.exit, or does that need to throw an exception as well?

The technique I usually do for a utility that I want callable by another class as well as executable from the command line is for the main() routine to delegate to another public method which throws exceptions and doesn't call System.exit().  Then the main() routine catches any exceptions and calls System.exit(1) if there is an exception or System.exit(0) if there isn't one.  Then classes call the other public method and main() is only used from the command-line.

Does that work here?

Thanks,

David

> Remove System.exit() calls from the DB2jServerImpl.java
> -------------------------------------------------------
>
>          Key: DERBY-214
>          URL: http://issues.apache.org/jira/browse/DERBY-214
>      Project: Derby
>         Type: Bug
>   Components: Network Server
>     Versions: 10.1.0.0
>     Reporter: Kathey Marsden

>
> The System.exit() calls needs to be removed from the 
> DB2jServerImpl.java as this results in the entire application 
> (example - Eclipse which is running the Network Server inside 
> it) getting shut down.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by Daniel John Debrunner <dj...@debrunners.com>.
David Van Couvering wrote:

> Well, that's enlightening, I wasn't aware that an exception thrown by
> main caused an exit status of 1.  That definitely sounds like the right
> approach.  If it's not a commonly accepted practice, it should be :)

Sounds good, the rule for the emebedded engine was always:

"remember pure Java, embedded, pure Java & embedded". :-)

Never make assumptions that your Java program is controlling the JVM and
has the right to call methods like System.exit, then multiple Java
"main" programs can hook up together without problems.

Dan.


Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by David Van Couvering <Da...@Sun.COM>.
Well, that's enlightening, I wasn't aware that an exception thrown by 
main caused an exit status of 1.  That definitely sounds like the right 
approach.  If it's not a commonly accepted practice, it should be :)

David

Kathey Marsden wrote:

> David Van Couvering wrote:
> 
> 
>>We could add an argument that indicates whether or not the main
>>program should call System.exit() or just return.  It's very valuable
>>to have a non-zero exit status when calling a command from the
>>command-line, for better scriptability...
>>
>>e.g. "-noSysExit"
>>
>>But I think what would be better is if applications like Eclipse don't
>>call main() but call the execute() method, which only throws an
>>exception.   This same issue exists for all the Derby tools, and it
>>would be good if we had a policy that didn't require a "-noSysExit"
>>option on every command.
>>
>>I can add an execute() method to NetworkServerControl so it's on the
>>same class as the main() method.
> 
> 
> What do you think about main throwing an exception?  If we can do that
> then it might  avoid changing the public API or doc.
> I don't know if that is a commonly accepted practice or not. I tried this.
> 
> public static void main(String[] args) throws Exception
>     {
>         conntype = null;
>         if (args.length < 1 || args[0].equals("throw"))
>             throw new Exception ("main throws exception");
>         else if (args[0].equals("exit0"))
>                  System.exit(0);
>         else if (args[0].equals("exit1"))
>             System.exit(1);
>         else if (args[0].equals("return"))
>             return;
>     }
> $ java MainException throw
> Exception in thread "main" java.lang.Exception: main throws exception
>         at MainException.main(MainException.java:20)
> $ echo $?
> 1
> $ java MainException return
> $ echo $?
> 0
> $ java MainException exit1
> $ echo $?
> 1
> $ java MainException exit0
> $ echo $?
> 0
> 
> 
> 

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by RPost <rp...@pacbell.net>.
> "David Van Couvering" wrote:

> Subject: Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from
the DB2jServerImpl.java

I found an interesting article from our friends of the 'Blue' persuasion
that discusses the JVMs use of hardware signals and how to use shutdown
hooks that come into play when the JVM is shutting down for any reason.

http://www-106.ibm.com/developerworks/ibm/library/i-signalhandling/

Not that it helps for the issue being discussed but it is closely related.




Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by David Van Couvering <Da...@Sun.COM>.
OK, I have searched everywhere but can find no reference to confirm or 
deny that an exception on main guarantees a return status of 1 and no 
exception a return status of 0.

The code samples and tutorials generally *don't* have main() throwing an 
exception, and any questions about exit status always refer people to 
using System.exit()

I also found a code sample that allows a calling application to prevent 
a VM exit.  What you do is define a security manager that can catch a 
ignore a System.exit() call from the application you are embedding and 
turn it into an exception.

I have an email out to our J2SE folks asking if the exit behavior is 
standardized or depedent on the VM implementation.  If it *isn't* 
standardized, and I suspect it's not, I suggest that we use 
System.exit(), and advise the Eclipse folks how to catch that using a 
security manager.

That said, I also think we should have and document a pattern for our 
tools where there is a callable method that throws an exception which 
main() delegates to, as Jeremy suggests.  Most embedding apps can just 
do that, rather than go through the hoops of writing a security manager.

Thanks,

David

Kathey Marsden wrote:

>>David Van Couvering wrote:
>>
>>
>>>I like Jeremy's idea of a JavaBean interface
>>
> 
> I guess things are always more complicated than you think.   When Rajesh
> brought the Eclipse issue  up, I had suggested that he use the
> NetworkServerControl.API, for example NetworkServerControl.start() and
> NetworkServerControl.shutdown() and I think he had said that there was
> some sort of problem with that but found some other workaround.  So,
> would using  the JavaBean interface mean that main would continue to
> call System.exit()?   If so, I don't know if it solves the original
> problem or addresses Dan's concern that  we not make assumptions about
> how we are being called.
> 
> 
> 
> Kathey
> 
> 
> 
> 
> 
> 
> 
> 

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by Kathey Marsden <km...@sbcglobal.net>.
> David Van Couvering wrote:
>
>> I like Jeremy's idea of a JavaBean interface
>

I guess things are always more complicated than you think.   When Rajesh
brought the Eclipse issue  up, I had suggested that he use the
NetworkServerControl.API, for example NetworkServerControl.start() and
NetworkServerControl.shutdown() and I think he had said that there was
some sort of problem with that but found some other workaround.  So,
would using  the JavaBean interface mean that main would continue to
call System.exit()?   If so, I don't know if it solves the original
problem or addresses Dan's concern that  we not make assumptions about
how we are being called.



Kathey









Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by David Van Couvering <Da...@Sun.COM>.
These are good points.  Are we OK with setPort(), setHost() and 
execute() being static methods, or do we feel creating a new instance is 
the way to go.  I would vote for creating an instance, but I'm worried 
existing code has a heavy dependence on static methods and static variables.

BTW, Jeremy, the main use of ij as an embedded class is the test 
harness.  It uses ij to read scripts and print results.  A significant 
part of our testing is done that way...  and right now the harness calls 
ij.main(args)...

The other annoying thing about ij as the tool used by the harness, while 
I'm on the subject, is that it depends heavily on properties for 
arguments -- things are specific as system properties or in a properties 
file.  This makes it very hard to run different instances of ij with a 
different configuration.  I was forced to generate a different 
properties file for each thread.  ij also does connection pooling, so if 
you try to run say four different instances of ij and you want each 
instance to go against a different database, you get some very 
unexpected results.  I learned this the hard way when I tried to use the 
test harness infrastructure to build a test that scales across multiple 
databases in the same VM.  Basically not achievable with ij.  I guess I 
should log a bug and stop whining... :)

David

Oyvind.Bakksjo@Sun.COM wrote:

> Jeremy Boynes skrev:
> 
>> What I don't like with the arg array is the lack of context and type 
>> safety.
>>
>> For example, I find
>>
>> cmd.execute(new String[]{"-p", "1567", "-h", "localhost" })
>>
>> less meaningful than
>>
>> cmd.setPort(1567);
>> cmd.setHost("localhost");
>> cmd.execute();
>>
>> and probably harder to implement when you add in error checking.
> 
> 
> I totally agree with you. Also, if you write
> 
>   cmd.setProt(1567);
>   cmd.setHots("localhost");
>   cmd.execute();
> 
> you will get an error at compile time, whereas if you write
> 
>   cmd.execute(new String[] { "-P", "1567", "-H", "localhost" });
> 
> the best you can hope for is an exception at runtime.
> 

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by Oy...@Sun.COM.
Jeremy Boynes skrev:
> What I don't like with the arg array is the lack of context and type 
> safety.
> 
> For example, I find
> 
> cmd.execute(new String[]{"-p", "1567", "-h", "localhost" })
> 
> less meaningful than
> 
> cmd.setPort(1567);
> cmd.setHost("localhost");
> cmd.execute();
> 
> and probably harder to implement when you add in error checking.

I totally agree with you. Also, if you write

   cmd.setProt(1567);
   cmd.setHots("localhost");
   cmd.execute();

you will get an error at compile time, whereas if you write

   cmd.execute(new String[] { "-P", "1567", "-H", "localhost" });

the best you can hope for is an exception at runtime.

-- 
Øyvind Bakksjø
Sun Microsystems, Web Services, Database Technology Group
Haakon VII gt. 7b, N-7485 Trondheim, Norway
Tel: x43419 / +47 73842119, Fax: +47 73842101

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by Jeremy Boynes <jb...@apache.org>.
David Van Couvering wrote:
> Whoa, I was just trying to fix the System.exit() problem :)
> 
> I agree with you that there is a bit too many responsibilities for one 
> object, and that parsing of arguments should be separated from execution 
> of logic.  However, I don't think that I should attack the separation of 
> establishing a remote connection and driving the wire protocol as part 
> of this bug.  I think we should log a separate bug for that issue, I 
> think it's a great thought for a more flexible design.
> 

I tend to agree. KISS for now and let's tackle the bigger issue when it 
has had a bit more thought.

<snip/>
> 
> However, other Derby tools, however, like ij and dblook, don't have this 
> command-based interface.  They do need some kind of "execute" method 
> that matches the way it is invoked from the command-line.  As discussed, 
> if the behavior of exit status when returning from main() is well 
> defined by the Java spec, then we can just use main with no call to 
> System.exit().  Otherwise, we should provide a separate execute() method 
> for embedding applications.
> 

ij seems wierd to me as I would expect an app just to use raw JDBC - 
perhaps commands to execute a script would be useful.

> If we decide upon a separate execute() method, my question still is, 
> what is the easier way to invoke this execute method, using an arg 
> array, or by instantiating an instance and setting bean properties?   I 
> think this is an indepedent question from any separation of concern 
> issues within the tool itself.  I personally think an arg array is 
> easier, but perhaps I'm missing an important architectural issue.
> 

What I don't like with the arg array is the lack of context and type safety.

For example, I find

cmd.execute(new String[]{"-p", "1567", "-h", "localhost" })

less meaningful than

cmd.setPort(1567);
cmd.setHost("localhost");
cmd.execute();

and probably harder to implement when you add in error checking.

--
Jeremy

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by David Van Couvering <Da...@Sun.COM>.
Hi, Kathey.  My background is definitely on the networking/runtime side 
more than in database internals.  I looked at the NetworkServer and was 
a little daunted.  It didn't help that there was no client code to look 
at, but that has recently changed.

I humbly request that I try to do some simple little patches (although 
look at my last attempt to find something simple :) ), I can focus on 
NetworkServer small patches, and start getting comfortable with the 
code.  Perhaps we can do some email exchanges where you help me through 
the architecture of the NetworkServer, it was a little hard to follow.

David

Kathey Marsden wrote:

> Firstly, I would like to say that I am so happy that this little bug
> brought such big thinkers to Network Server.
> 
> David Van Couvering wrote:
> 
> 
>>I agree with you that there is a bit too many responsibilities for one
>>object
> 
> 
> 
> I think that this is highly prevalent issue with Network Server in
> general.  For instance, I think clearly the parameter metadata needs to
> be separated out from DRDAStatement  and the respnosibilities of 
> DRDAConnThread are quite immense and probably need to be evaluated and
> delegated accordingly.  I have lacked the  time and confidence to go in
> and tear these  things apart and put them back together.   I hope you
> will consider sticking around Network Server for a while.    It's seems
> to me you have been shopping around for a place to do some good and I
> think you could really make a big difference here.    If so, I would
> like to facilitate in any way I can, but we should pick that up on a new
> thread #:)
> 
> 
> Thanks
> 
> Kathey
> 
> 
> 
> 
> 

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by Kathey Marsden <km...@sbcglobal.net>.
Firstly, I would like to say that I am so happy that this little bug
brought such big thinkers to Network Server.

David Van Couvering wrote:

>
> I agree with you that there is a bit too many responsibilities for one
> object


I think that this is highly prevalent issue with Network Server in
general.  For instance, I think clearly the parameter metadata needs to
be separated out from DRDAStatement  and the respnosibilities of 
DRDAConnThread are quite immense and probably need to be evaluated and
delegated accordingly.  I have lacked the  time and confidence to go in
and tear these  things apart and put them back together.   I hope you
will consider sticking around Network Server for a while.    It's seems
to me you have been shopping around for a place to do some good and I
think you could really make a big difference here.    If so, I would
like to facilitate in any way I can, but we should pick that up on a new
thread #:)


Thanks

Kathey






Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by David Van Couvering <Da...@Sun.COM>.
Whoa, I was just trying to fix the System.exit() problem :)

I agree with you that there is a bit too many responsibilities for one 
object, and that parsing of arguments should be separated from execution 
of logic.  However, I don't think that I should attack the separation of 
establishing a remote connection and driving the wire protocol as part 
of this bug.  I think we should log a separate bug for that issue, I 
think it's a great thought for a more flexible design.

For this bug, I could use it as an opportunity to take all command-line 
parsing *out* of DB2jServerImpl, that makes a lot of sense. 
DB2jServerImpl should only be called by NetworkServerControl anyway, and 
should present a more classic object abstraction and not have anything 
to do with argument parsing.  BTW, it was my mistake to use 
DB2jServerImpl in the example below, it should have been 
NetworkServerControl.

In this particular example, NetworkServerControl also has methods for 
each command, and the Derby docs explicitly document that this is how 
you work with the network server in embedded mode.  So an embedding app 
shouldn't ever have to or need to call main() or any routine that just 
takes an array of args, and doesn't need the model I propose below.

However, other Derby tools, however, like ij and dblook, don't have this 
command-based interface.  They do need some kind of "execute" method 
that matches the way it is invoked from the command-line.  As discussed, 
if the behavior of exit status when returning from main() is well 
defined by the Java spec, then we can just use main with no call to 
System.exit().  Otherwise, we should provide a separate execute() method 
for embedding applications.

If we decide upon a separate execute() method, my question still is, 
what is the easier way to invoke this execute method, using an arg 
array, or by instantiating an instance and setting bean properties?   I 
think this is an indepedent question from any separation of concern 
issues within the tool itself.  I personally think an arg array is 
easier, but perhaps I'm missing an important architectural issue.

Thanks,

David

Jeremy Boynes wrote:

> David Van Couvering wrote:
> 
>>
>> Also, the JavaBean approach assumes you create an instance of the 
>> beast, and I have noticed that many command-line classes have most of 
>> their code in static methods and use static variables (not that they 
>> should, but that's what they do).  Also, it might actually be easier 
>> to set up an array of Strings rather than call a bunch of set methods, 
>> especially if you can create the array in-place, e.g.
>>
>> DB2jServerImpl.main(new String[] { "ping", "-p", "2000"} );
>>
>> rather than
>>
>> DB2jServerImpl impl = new DB2jServerImpl()
>> impl.setCommand("ping");
>> impl.setPort("2000");
>> impl.execute();
>>
> 
> My concern here is coming from confusion in the responsibilities between 
> NetworkServerControl and DB2jServerImpl. For example, there are two ways 
> to set the maxthreads:
> 
> 1) new NetworkServerControl().setMaxThreads(100);
> 
> 2) NetworkServerControl.main(
>      new String[]{"maxthreads", "100"});
> 
> Ultimately these both end up calling DB2jServerImpl.netSetMaxThreads()
> 
> DB2jServerImpl is doing three completely different things here: it is 
> setting up the remote connection, it is driving the wire protocol to the 
> remote server (see the impl of netSetMaxThreads), and it is responsible 
> for parsing and verifying the command line arguments passed in. I think 
> these concerns can be separated resulting in a simpler implementation 
> that is easier to embed and use from other tools such as Eclipse.
> 
> I would first suggest factoring out the connection setup and teardown - 
> perhaps a NetworkServerConnection class with hostname and port 
> properties (perhaps username, password or other credential) and an 
> execute method that takes a command object e.g.
> 
> public class NetworkServerConnection {
>    public void connect() throws TransportException;
>    public void close() throws TransportException;
> 
>    public Object execute(NetworkServerCommand cmd)
>       throws TransportException, CommandException;
> }
> 
> Each command (ping, maxthreads, etc) is represented by an object that 
> implements NetworkServerCommand and which can be set up with the 
> appropriate properties e.g.
> 
> public class SetMaxThreadsCommand implements NetworkServerCommand {
>    public void setMaxThreads(int threads);
> }
> 
> Each command would know how to write itself to the wire; heck if you 
> were prepared to break backward compatibility you could simplify things 
> further by just using serialization.
> 
> For command line support, NetworkServerControl.main parses the 
> arguments, creates a NetworkServerConnection and the appropriate command 
>  and then submits it to the remote server. Basically it just contains 
> implementation for handling the command line syntax.
> 
> For embedded use, a tool can create and maintain a connection for as 
> long as necessary, getting the connection parameters any way it wants 
> (e.g. a host/user/password dialog). The commands can be created and 
> submitted in response to UI events just like any others. Both the 
> connection and the commands can use beaninfo to define their properties.
> 
> Although there are more moving parts in this, I think overall it is a 
> more maintainable solution as the concerns of connection, commands and 
> UI have been clearly separated.
> 
> -- 
> Jeremy

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by Jeremy Boynes <jb...@apache.org>.
David Van Couvering wrote:
> 
> Also, the JavaBean approach assumes you create an instance of the beast, 
> and I have noticed that many command-line classes have most of their 
> code in static methods and use static variables (not that they should, 
> but that's what they do).  Also, it might actually be easier to set up 
> an array of Strings rather than call a bunch of set methods, especially 
> if you can create the array in-place, e.g.
> 
> DB2jServerImpl.main(new String[] { "ping", "-p", "2000"} );
> 
> rather than
> 
> DB2jServerImpl impl = new DB2jServerImpl()
> impl.setCommand("ping");
> impl.setPort("2000");
> impl.execute();
> 

My concern here is coming from confusion in the responsibilities between 
NetworkServerControl and DB2jServerImpl. For example, there are two ways 
to set the maxthreads:

1) new NetworkServerControl().setMaxThreads(100);

2) NetworkServerControl.main(
      new String[]{"maxthreads", "100"});

Ultimately these both end up calling DB2jServerImpl.netSetMaxThreads()

DB2jServerImpl is doing three completely different things here: it is 
setting up the remote connection, it is driving the wire protocol to the 
remote server (see the impl of netSetMaxThreads), and it is responsible 
for parsing and verifying the command line arguments passed in. I think 
these concerns can be separated resulting in a simpler implementation 
that is easier to embed and use from other tools such as Eclipse.

I would first suggest factoring out the connection setup and teardown - 
perhaps a NetworkServerConnection class with hostname and port 
properties (perhaps username, password or other credential) and an 
execute method that takes a command object e.g.

public class NetworkServerConnection {
    public void connect() throws TransportException;
    public void close() throws TransportException;

    public Object execute(NetworkServerCommand cmd)
       throws TransportException, CommandException;
}

Each command (ping, maxthreads, etc) is represented by an object that 
implements NetworkServerCommand and which can be set up with the 
appropriate properties e.g.

public class SetMaxThreadsCommand implements NetworkServerCommand {
    public void setMaxThreads(int threads);
}

Each command would know how to write itself to the wire; heck if you 
were prepared to break backward compatibility you could simplify things 
further by just using serialization.

For command line support, NetworkServerControl.main parses the 
arguments, creates a NetworkServerConnection and the appropriate command 
  and then submits it to the remote server. Basically it just contains 
implementation for handling the command line syntax.

For embedded use, a tool can create and maintain a connection for as 
long as necessary, getting the connection parameters any way it wants 
(e.g. a host/user/password dialog). The commands can be created and 
submitted in response to UI events just like any others. Both the 
connection and the commands can use beaninfo to define their properties.

Although there are more moving parts in this, I think overall it is a 
more maintainable solution as the concerns of connection, commands and 
UI have been clearly separated.

--
Jeremy

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by Kathey Marsden <km...@sbcglobal.net>.
David Van Couvering wrote:

>   I assumed Eclipse had a reason for going this route.  To be honest,
> I am concerned that we are trying to bend over backwards for the
> Eclipse folks when we should be telling them how to use this in the
> right way.
>
Actually I wanted to clarify here that the original request came not
from Eclipse, but from the folks making the Derby plugin for Eclipse,
which is a thing that actually exists so I assume that they found a
workaround.  I  thought it would be nice (and easy) to avoid the exit
from  the main method and possibly helpful, so filed the bug in Jira and
I thought someone might want to pick it up.  So,  you might find it  is
not worth the time to pursue if it is hard or messy which it looks like
this might be.   My concern is that you might be bending over backwards
for exactly nobody.  

>
> This of course hinges on whether or not the exit status of a VM is
> defined when you throw an exception (or not) from main().  If it's
> well-defined, then we can just have main() throw Exception and be done
> with it.
>
agreed.

> I'll try to get an answer from the J2SE folks.  In meanwhile I'll put
> this task on hold and go work on something else :)
>
Sounds like a good  plan. Thanks for looking at this and thanks to all
for catching the fact that throwing an Exception from main  might not be
a standard  thing to do.  If it is,  that would be great and we could do
the same sort of thing for ij and the other tools.  If not, I think your
idea of a standardized inteface is a good one if  you or someone else
thinks it is worth the effort.


Kathey




Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by David Van Couvering <Da...@Sun.COM>.

Kathey Marsden wrote:

> David Van Couvering wrote:
> 
> 
>>Hi, all.  I have done further investigation, and conversations I have
>>had convince me that (a) System.exit() is the proper way to set an
>>exit code and (b) embedding apps in general should not be calling
>>main(), and (c) since we have a policy of always expecting to be
>>embedded, tools should have a policy of providing a callable execute()
>>method that doesn't do System.exit() but instead throws exceptions.
>>
> 
> 
>>DB2jServerImpl.main(new String[] { "ping", "-p", "2000"} );
>>
>>rather than
>>
>>DB2jServerImpl impl = new DB2jServerImpl()
>>impl.setCommand("ping");
>>impl.setPort("2000");
>>impl.execute();
>>
> 
> DB2jServerImpl  is not a public class. NetworkServerControl is where the
> public api lives, so if we did use the JavaBean
> or execute approach the methods would live  there.

OK, point taken.

> 
> 
>>So, I would like to propose the following:
>>
>>- Define a new abstract class, e.g. org.apache.derby.tools.BaseTool,
>>that looks something like this:
>>
>>public abstract class BaseTool
>>{
> 
> 
> I feel a little funny about NetworkServer being called a tool, but maybe
> it's ok for NetworkServerControl  (a tool that controls the server?). 

Names are always a struggle.  I was thinking the same thing, actually. 
On the drive home, I thought that perhaps BaseMain was a better name for 
the base class.  It's "something that has a main routine."

> 
> 
>>  public abstract void execute(String[] args) throws Exception;
>>
>>  /**
>>  * Basic main routine, can be overridden if needed
>>  */
>>  public static void main(String[] args)
>>  {
>>    try
>>    {
>>      execute(args);
>>    }
>>    catch ( Exception e )
>>    {
>>      e.printStackTrace();
>>      System.exit(1);
>>    }
>>    System.exit(0);
>>  }
>>}
>>
>>and then have our tools implement this, e.g.
>>
>>public class MyTool extends BaseTool
>>{
>>  public void execute(String[] args) throws Exception
> 
> 
> Should this be:
>     public static void execute(String[] args) throws Exception?

Yes, sorry

> 
> 
>>  {
>>    // yada yada
>>  }
>>}
>>
>>and then applications can do
>>
>>MyTool.execute(new String{ "ping" });
>>
>>Comments?
> 
> 
> Well my comment is that I am glad I took this off the starter task list
> when I saw you picked it up.

:)

> 
> But I  have a question.  With regard to Network Server, would this just
> be an additional way to control network server if you would prefer to
> use execute instead of the existing NetworkServerControl API?  If so, 
> would one be preferred over the other?

Well, I am still learning Derby, but I did have the same question.  I 
assumed Eclipse had a reason for going this route.  To be honest, I am 
concerned that we are trying to bend over backwards for the Eclipse 
folks when we should be telling them how to use this in the right way.

I am going to push harder with the J2SE team to try and find an answer 
about the specified behavior for exit status when you return from 
main(), but in general it seems like a bad idea to call main() of a 
tool, and you shouldn't be that surprised if it does a System.exit() to 
set the exit status...

> 
> I asked Rajesh to respond regarding his original Eclipse requirements,
> but while the execute thing sounds interesting, I  wonder how it
> addresses the Eclipse calling model?  Maybe  a static method is all that
> is needed and  execute would suffice if it is a static method.

See above, I'd like to understand their requirements and why they aren't 
calling NetworkServerControl directly, which would solve their problems.

Not that we still shouldn't fix this and have a general policy about 
embedding classes with main() methods.

> 
> 
> Still also I wonder about  what Dan said:
> 
> Never make assumptions that your Java program is controlling the JVM and
> has the right to call methods like System.exit, then multiple Java
> "main" programs can hook up together without problems.

Yes, that's fair, but if we have a documented mechanism for embedding 
the programs using a different method, then we get the best of both 
worlds: we can control exit status if main() is called, and we can be 
embedded.

This of course hinges on whether or not the exit status of a VM is 
defined when you throw an exception (or not) from main().  If it's 
well-defined, then we can just have main() throw Exception and be done 
with it.

> 
> 
> I guess that is how I would like to see it in an ideal world. Maybe that is not possible, but   I would like to hear a little bit more input before we make such a decision about the public API's.  

I'll try to get an answer from the J2SE folks.  In meanwhile I'll put 
this task on hold and go work on something else :)

David

> 
> 
> Thanks
> 
> Kathey
> 
> 

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by Kathey Marsden <km...@sbcglobal.net>.
David Van Couvering wrote:

> Hi, all.  I have done further investigation, and conversations I have
> had convince me that (a) System.exit() is the proper way to set an
> exit code and (b) embedding apps in general should not be calling
> main(), and (c) since we have a policy of always expecting to be
> embedded, tools should have a policy of providing a callable execute()
> method that doesn't do System.exit() but instead throws exceptions.
>

>
> DB2jServerImpl.main(new String[] { "ping", "-p", "2000"} );
>
> rather than
>
> DB2jServerImpl impl = new DB2jServerImpl()
> impl.setCommand("ping");
> impl.setPort("2000");
> impl.execute();
>
DB2jServerImpl  is not a public class. NetworkServerControl is where the
public api lives, so if we did use the JavaBean
or execute approach the methods would live  there.

> So, I would like to propose the following:
>
> - Define a new abstract class, e.g. org.apache.derby.tools.BaseTool,
> that looks something like this:
>
> public abstract class BaseTool
> {

I feel a little funny about NetworkServer being called a tool, but maybe
it's ok for NetworkServerControl  (a tool that controls the server?). 

>
>   public abstract void execute(String[] args) throws Exception;
>
>   /**
>   * Basic main routine, can be overridden if needed
>   */
>   public static void main(String[] args)
>   {
>     try
>     {
>       execute(args);
>     }
>     catch ( Exception e )
>     {
>       e.printStackTrace();
>       System.exit(1);
>     }
>     System.exit(0);
>   }
> }
>
> and then have our tools implement this, e.g.
>
> public class MyTool extends BaseTool
> {
>   public void execute(String[] args) throws Exception

Should this be:
    public static void execute(String[] args) throws Exception?

>   {
>     // yada yada
>   }
> }
>
> and then applications can do
>
> MyTool.execute(new String{ "ping" });
>
> Comments?

Well my comment is that I am glad I took this off the starter task list
when I saw you picked it up.

But I  have a question.  With regard to Network Server, would this just
be an additional way to control network server if you would prefer to
use execute instead of the existing NetworkServerControl API?  If so, 
would one be preferred over the other?

I asked Rajesh to respond regarding his original Eclipse requirements,
but while the execute thing sounds interesting, I  wonder how it
addresses the Eclipse calling model?  Maybe  a static method is all that
is needed and  execute would suffice if it is a static method.


Still also I wonder about  what Dan said:

Never make assumptions that your Java program is controlling the JVM and
has the right to call methods like System.exit, then multiple Java
"main" programs can hook up together without problems.


I guess that is how I would like to see it in an ideal world. Maybe that is not possible, but   I would like to hear a little bit more input before we make such a decision about the public API's.  


Thanks

Kathey



Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by David Van Couvering <Da...@Sun.COM>.
Hi, all.  I have done further investigation, and conversations I have 
had convince me that (a) System.exit() is the proper way to set an exit 
code and (b) embedding apps in general should not be calling main(), and 
(c) since we have a policy of always expecting to be embedded, tools 
should have a policy of providing a callable execute() method that 
doesn't do System.exit() but instead throws exceptions.

Regarding Jeremy's suggestions:

I wasn't sure, and I checked: Callable is new to JDK 1.5.  Unless I am 
mistaken, we can't take advantage of new JDK 1.5 features at this time, 
am I right?

In terms of Runnable, that would work, but I am a bit concerned because 
the real semantics of Runnable are that you can run it as a separate 
thread, and it could be confusing to overload it this meaning with our 
implied meaning that it can be embedded and executed.  We could define 
our own interface that all our tools follow that has the very specific 
semantics of "this is a tool that you can embed, you need to call the 
execute() method to avoid the VM exiting".

Also, the JavaBean approach assumes you create an instance of the beast, 
and I have noticed that many command-line classes have most of their 
code in static methods and use static variables (not that they should, 
but that's what they do).  Also, it might actually be easier to set up 
an array of Strings rather than call a bunch of set methods, especially 
if you can create the array in-place, e.g.

DB2jServerImpl.main(new String[] { "ping", "-p", "2000"} );

rather than

DB2jServerImpl impl = new DB2jServerImpl()
impl.setCommand("ping");
impl.setPort("2000");
impl.execute();

So, I would like to propose the following:

- Define a new abstract class, e.g. org.apache.derby.tools.BaseTool, 
that looks something like this:

public abstract class BaseTool
{
   public abstract void execute(String[] args) throws Exception;

   /**
   * Basic main routine, can be overridden if needed
   */
   public static void main(String[] args)
   {
     try
     {
       execute(args);
     }
     catch ( Exception e )
     {
       e.printStackTrace();
       System.exit(1);
     }
     System.exit(0);
   }
}

and then have our tools implement this, e.g.

public class MyTool extends BaseTool
{
   public void execute(String[] args) throws Exception
   {
     // yada yada
   }
}

and then applications can do

MyTool.execute(new String{ "ping" });

Comments?

David

Jeremy Boynes wrote:

> David Van Couvering wrote:
> 
>> I like Jeremy's idea of a JavaBean interface, although I don't 
>> understand why it needs to implement Runnable or Callable, is that 
>> just so it uses a standard mechanism for a no-arg execute method?
>>
> 
> Yes.
> -- 
> Jeremy

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by Jeremy Boynes <jb...@apache.org>.
David Van Couvering wrote:
> I like Jeremy's idea of a JavaBean interface, although I don't 
> understand why it needs to implement Runnable or Callable, is that just 
> so it uses a standard mechanism for a no-arg execute method?
> 

Yes.
--
Jeremy

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by David Van Couvering <Da...@Sun.COM>.
Wow, and I thought this was a simple fix :)

If Jeremy is right, and the exit status is not defined by J2SE when an 
exception is thrown, then this is a problem.  I'll look into this (I 
have to get on the road right now).

I also have always been uncomfortable calling main() from another 
program, and appreciate it when the class provides another interface.
I like Jeremy's idea of a JavaBean interface, although I don't 
understand why it needs to implement Runnable or Callable, is that just 
so it uses a standard mechanism for a no-arg execute method?

Thanks,

David

Jeremy Boynes wrote:

> Kathey Marsden wrote:
> 
>> David Van Couvering wrote:
>>
>>
>>> We could add an argument that indicates whether or not the main
>>> program should call System.exit() or just return.  It's very valuable
>>> to have a non-zero exit status when calling a command from the
>>> command-line, for better scriptability...
>>>
>>> e.g. "-noSysExit"
>>>
>>> But I think what would be better is if applications like Eclipse don't
>>> call main() but call the execute() method, which only throws an
>>> exception.   This same issue exists for all the Derby tools, and it
>>> would be good if we had a policy that didn't require a "-noSysExit"
>>> option on every command.
>>>
>>> I can add an execute() method to NetworkServerControl so it's on the
>>> same class as the main() method.
>>
>>
>>
>> What do you think about main throwing an exception?  If we can do that
>> then it might  avoid changing the public API or doc.
>> I don't know if that is a commonly accepted practice or not. I tried 
>> this.
>>
> 
> I have a couple of issues.
> 
> Firstly, I don't believe the behaviour of the JVM is defined so you 
> don't know what is going to happen to the info from the Exception. Also 
> running this under a GUI (e.g. using javaw) may result in loss of that 
> info all together as there may not be a console.
> 
> A bigger issue for me is that main is a static entry point that takes 
> command line arguments. This is OK for something called from an external 
> command line but makes little sense for something being embedded in 
> another tool.
> 
> I would prefer to see the public API as a JavaBean with properties and a 
> single noarg execute method (perhaps by implementing Runnable or 
> Callable). That way the user can instantitate it, initialize the 
> arguments in a typesafe way, and then execute it.
> 
> The command line interface then becomes a thin wrapper whose main method 
> creates the bean and sets the properties by parsing the arguments.
> 
> -- 
> Jeremy

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by Jeremy Boynes <jb...@apache.org>.
Kathey Marsden wrote:
> David Van Couvering wrote:
> 
> 
>>We could add an argument that indicates whether or not the main
>>program should call System.exit() or just return.  It's very valuable
>>to have a non-zero exit status when calling a command from the
>>command-line, for better scriptability...
>>
>>e.g. "-noSysExit"
>>
>>But I think what would be better is if applications like Eclipse don't
>>call main() but call the execute() method, which only throws an
>>exception.   This same issue exists for all the Derby tools, and it
>>would be good if we had a policy that didn't require a "-noSysExit"
>>option on every command.
>>
>>I can add an execute() method to NetworkServerControl so it's on the
>>same class as the main() method.
> 
> 
> What do you think about main throwing an exception?  If we can do that
> then it might  avoid changing the public API or doc.
> I don't know if that is a commonly accepted practice or not. I tried this.
> 

I have a couple of issues.

Firstly, I don't believe the behaviour of the JVM is defined so you 
don't know what is going to happen to the info from the Exception. Also 
running this under a GUI (e.g. using javaw) may result in loss of that 
info all together as there may not be a console.

A bigger issue for me is that main is a static entry point that takes 
command line arguments. This is OK for something called from an external 
command line but makes little sense for something being embedded in 
another tool.

I would prefer to see the public API as a JavaBean with properties and a 
single noarg execute method (perhaps by implementing Runnable or 
Callable). That way the user can instantitate it, initialize the 
arguments in a typesafe way, and then execute it.

The command line interface then becomes a thin wrapper whose main method 
creates the bean and sets the properties by parsing the arguments.

--
Jeremy

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by Kathey Marsden <km...@sbcglobal.net>.
David Van Couvering wrote:

> We could add an argument that indicates whether or not the main
> program should call System.exit() or just return.  It's very valuable
> to have a non-zero exit status when calling a command from the
> command-line, for better scriptability...
>
> e.g. "-noSysExit"
>
> But I think what would be better is if applications like Eclipse don't
> call main() but call the execute() method, which only throws an
> exception.   This same issue exists for all the Derby tools, and it
> would be good if we had a policy that didn't require a "-noSysExit"
> option on every command.
>
> I can add an execute() method to NetworkServerControl so it's on the
> same class as the main() method.

What do you think about main throwing an exception?  If we can do that
then it might  avoid changing the public API or doc.
I don't know if that is a commonly accepted practice or not. I tried this.

public static void main(String[] args) throws Exception
    {
        conntype = null;
        if (args.length < 1 || args[0].equals("throw"))
            throw new Exception ("main throws exception");
        else if (args[0].equals("exit0"))
                 System.exit(0);
        else if (args[0].equals("exit1"))
            System.exit(1);
        else if (args[0].equals("return"))
            return;
    }
$ java MainException throw
Exception in thread "main" java.lang.Exception: main throws exception
        at MainException.main(MainException.java:20)
$ echo $?
1
$ java MainException return
$ echo $?
0
$ java MainException exit1
$ echo $?
1
$ java MainException exit0
$ echo $?
0




Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by David Van Couvering <Da...@Sun.COM>.
We could add an argument that indicates whether or not the main program 
should call System.exit() or just return.  It's very valuable to have a 
non-zero exit status when calling a command from the command-line, for 
better scriptability...

e.g. "-noSysExit"

But I think what would be better is if applications like Eclipse don't 
call main() but call the execute() method, which only throws an 
exception.   This same issue exists for all the Derby tools, and it 
would be good if we had a policy that didn't require a "-noSysExit" 
option on every command.

I can add an execute() method to NetworkServerControl so it's on the 
same class as the main() method.

David

Kathey Marsden wrote:

> David Van Couvering (JIRA) wrote:
> 
> 
>> Is it OK for NetworkServerControl to call System.exit, or does that need to throw an exception as well?
>>
>>The technique I usually do for a utility that I want callable by another class as well as executable from the command line is for the main() routine to delegate to another public method which throws exceptions and doesn't call System.exit().  Then the main() routine catches any exceptions and calls System.exit(1) if there is an exception or System.exit(0) if there isn't one.  Then classes call the other public method and main() is only used from the command-line.
>> 
>>
> 
> 
> The execute() method which is the one with the System.exit is only
> called by NetworkServerControl.main()  so I guess it is the exit even
> from main that is causing a problem with eclipse.  For the exit(0),  I
> guess we could just return.  For the exit(1) case I am not entirely sure
> what  is appropriate.    Maybe  main should just throw the exception
> then we get an error exit but the calling program won't exit completely.
> 
> Rajesh filed the original case when he had a problem with eclipse
> exiting completely when he tried to use the main method from within
> eclipse.  Rajesh could you confirm that  that is the case?
> 
> Kathey
> 
> 
> 
> 
> 

Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java

Posted by Kathey Marsden <km...@sbcglobal.net>.
David Van Couvering (JIRA) wrote:

>
>  Is it OK for NetworkServerControl to call System.exit, or does that need to throw an exception as well?
>
>The technique I usually do for a utility that I want callable by another class as well as executable from the command line is for the main() routine to delegate to another public method which throws exceptions and doesn't call System.exit().  Then the main() routine catches any exceptions and calls System.exit(1) if there is an exception or System.exit(0) if there isn't one.  Then classes call the other public method and main() is only used from the command-line.
>  
>

The execute() method which is the one with the System.exit is only
called by NetworkServerControl.main()  so I guess it is the exit even
from main that is causing a problem with eclipse.  For the exit(0),  I
guess we could just return.  For the exit(1) case I am not entirely sure
what  is appropriate.    Maybe  main should just throw the exception
then we get an error exit but the calling program won't exit completely.

Rajesh filed the original case when he had a problem with eclipse
exiting completely when he tried to use the main method from within
eclipse.  Rajesh could you confirm that  that is the case?

Kathey