Nicole Gustavson

Greenhorn
+ Follow
since Jan 06, 2003
Cows and Likes
Cows
Total received
0
In last 30 days
0
Total given
0
Likes
Total received
0
Received in last 30 days
0
Total given
0
Given in last 30 days
0
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Nicole Gustavson

So it turns out the problem with the schema was that JAXB generates a set of classes for every top-level element and top-level complex type. XMLSPY (which generated our XML schema) creates a top-level element for every tag. So the solution was to change any element that doesn't require its own class into either a nested element, or a top-level simple type. Either one of these does the trick:
Thanks for the link, it was educational! It seems like there's no way to do what we want to do using JAXB. If you want to generate a class with properties, your XML schema has to have an element with attributes, not an element with subelements.

So, our choices are: change the XML schema to use attributes instead of subelements (may not be politically possible), or not use JAXB. It seems like we may have to drop JAXB.

So are there any alternatives other than writing our own data classes and XML parser using DOM? Can XSLT do anything for us?

Thanks again.
I'm very new to JAXB and would like to know if the following is possible. I have a schema which is already approved and in use, and would like to use JAXB to generate some data classes. I'm getting a bunch of classes that I would like to be attributes instead. Is it possible to get them as simple attributes instead of separate classes?

Here is an excerpt of the XML schema:



Is it possible to get Gender as just a String member in the Person class, instead of a separate Gender class?

Is it possible to do it without changing the input format of the XML file?



Thanks very much.

The difference is, this would happen only when necessary.


When's that?

One possible mode of error recovery -- which is out of scope IMHO -- would be to junk the existing Connection, create a new one, and retry.


Where would you put this code?

Another solution, one which leaves the ultimate decisions about error recovery to the client code, is to use a Strategy: together with your transport-specific Connection implementation, you could create a transport-specific RecoveryStrategy implementation.


Would this be simpler or more maintainable than a one-class adapter? Also, what is a "transport-specific Connection implementation", and how do you use it?

If that would have been all it's there for, then you could have junked the adapter. The Connection stub class generated by rmic satisfies this requirement in all respects.


Can the stub of a server-side remote class be accurately described as a client-side class? I have never heard that before. In my mind, a stub is an RMI implementation artifact, big time.
Consider the following requirements:
  • "There are three key parts: [...] a client-side database client part that handles the networking [not business logic] on behalf of the user interface"
  • "The remote client [not server] code that you write must provide all the public methods of the suncertify.db.Data class"
  • Under the Writing Data Client heading: "...you should create a client program. This implementation should include a class that implements the same public methods as the suncertify.db.Data class..."

  • I believe you are questionably reinterpreting a repeatedly-mentioned, reasonably specific requirement.

    As an aside -- using a client-side adapter, you can implement lock() and unlock() as specified without using an RMI Factory!


    How? (Just curious.)

    Introducing an adapter class just to abstract a completely theoretical transport layer that doesn't throw IOException is over-engineering.


    Them's fightin' words, Pete! But seriously, I do appreciate the thought-provoking things you have to say.

    At the same time, it is out of scope for the assignment. That also means that your adapter object doesn't serve a useful purpose in the assignment.


    Points to consider:
  • Is good OO design out of scope for this project?
  • Is the encapsulation of application layers (i.e. shielding each layer from the implementation details of the other layers) a part of good OO design?
  • Is appropriate exception propagation a part of the proper encapsulation of application layers?


  • Thanks for the discussion.

    Thank you.
    - Nicole.
    Hi Peter,
    Thanks for answering my post... it was so verbose I was afraid no one would be able to get through it.
    3 questions to you...
    1. What do you do if you can't make MonkeyException extend IOException? (SqlException doesn't extend IOException.)
    2. What do clients do with the IOException?
    3. What if someone comes up with a way they want to recover from all RemoteExceptions, MonkeyExceptions, or IOExceptions, or do some special treatment of one of these? Where would you put the code?
    I've already implemented my "adapter" class (it's just the "client-side class that implements the public methods of Data"). I put all my RMI-involved classes, including this one, into a "remotedb" package and no class outside that package knows anything about RMI, including RemoteException or anything. The encapsulation really appeals to me.
    Now I'm off to search for the threads you mentioned -- I'm curious to see if anyone has had the same design, and/or the same thoughts.
    BTW, what really started me thinking about changing my design (I originally had it much as you mention), was reading a couple of good articles on exceptions:
    Designing With Exceptions
    and
    Does Java Need Checked Exceptions?: the article and subsequent discussion raise a lot of good questions. [for example, I was opposed to the concept of checked exceptions going in, but after reading the discussion I was totally won over to the pro-checked camp.]
    Reading about the fundamental purpose of exception handling, which is to handle exceptions (as opposed to work around or somehow ignore them), really convinced me that clients of Database should not have to know about any exceptions but DatabaseExceptions. The client of a Database is simply incapable of handling a RemoteException, IOException, etc. Exception handling is so much more than a try/catch block.
    The compromise of having Database throw RemoteExceptions or IOExceptions just seems like a workaround, an avoidance of the real issue, to me.
    Thanks again
    - Nicole.
    Hi Pascal,
    No, my client instantiates Data directly in local mode, so I didn't make it package visibility. I'm not worried about locking in local mode, so I didn't feel I needed to put a wrapper around Data.
    Hope that answers your question.
    - Nicole.
    Hiya Christian, Peter, everyone,
    I've seen mention of the following interface relationships:

    Then the client uses it something like this:

    This is fine as long as all possible databases only throw RemoteException and DatabaseException; but it causes problems when you create a different type of database. For an example, take a MonkeyDatabase that uses intelligent monkeys to remember and share data. Each method in MonkeyDatabase throws MonkeyException, which includes such categories as SleepingMonkeyException or DrunkenMonkeyException. If I want my clients to use this database class, I now have to alter the Database interface to have all of its methods throw DatabaseException, RemoteException, and MonkeyException. Worse yet, all of my client code now has to be rewritten to catch MonkeyException.
    There are several alternatives that I can think of:
    1)
    You can have the Database superinterface throw Exception, to cover every type of database you will ever come across. Now all of your client code has to be rewritten to catch Exception. Yech! If you are catching Exception all over the place, you can forget recovering from recoverable Exceptions -- recovery code would have to be added to each client method call.
    2)
    You can have your clients only make use of one particular type of Database. For instance, Program A knows it's only going to use a RemoteDatabase so it only has to catch RemoteException and DatabaseException. If it wants to use MonkeyDatabase, it will specifically create a MonkeyDatabase and not make use of the Database interface. In this case, is there really any benefit to having a Database superinterface? A bit, in that you know its subclasses are going to implement certain methods. But you can't actually make use of it in your clients.
    3)
    (It's the last one so you know this is the one I like ) You can create a Database superinterface in which all the methods throw only DatabaseException. All of your clients will use this interface and only have to catch DatabaseException. You then create a MonkeyDatabaseClient that implements Database, delegates all calls to a MonkeyDatabase, and handles all MonkeyExceptions.
    Something like this:

    You get the idea. The Database interface stands on its own independent of any subclass, clients can enjoy a consistent unchanging interface, and there is a possibility of a consistent error recovery mechanism for each individual database implementation.
    There must be a pattern for this -- facade or adapter or something -- help me out? Then the class would be called MonkeyDatabaseAdapter.
    You can extrapolate this example to say, a SqlDatabase that throws SqlExceptions or something, but I can't imagine why you would ever need one of those.
    - Nicole.
    Disclaimer: No animals were harmed or forced to imbibe alcoholic beverages in the making of this post.
    [ January 19, 2003: Message edited by: Nicole Gustavson ]
    Fixing code and such
    [ January 19, 2003: Message edited by: Nicole Gustavson ]
    Okay Peter, you've convinced me I have to include client identification in my project, and that my original interpretation of the requirements was lacking. This is mainly because, as you say, a crashed client is an everyday occurrence that really has to be dealt with. Regardless of whether it helps me get a better score or not (I think it will), I'm glad to learn a few more things about RMI.
    Now could you (or anyone else who's willing) review my proposed server design? It differs from most I have read about, so I'd appreciate any input.
    public interface RemoteDataFactory extends Remote
    public class RemoteDataFactoryImpl extends UnicastRemoteObject
    public interface RemoteData extends Remote, Unreferenced
    public class RemoteDataImpl extends UnicastRemoteObject
    Clients get their own instance of RemoteData via the RemoteDataFactory.
    There is a Locker class which performs locking, and synchronization of lock and unlock methods.
    The Data object has an instance of the Locker class, which it delegates lock and unlock calls to.
    The RemoteDataImpl delegates calls to the Data object. RemoteDataImpl maintains a list of records currently locked by this connection. The lock() method first calls Data.lock(), then adds the record to the list. The unlock() method checks this list before deciding to perform Data.unlock(). When unreferenced, RemoteDataImpl will unlock all locks in the list.
    The benefits of this solution, as I see it, are:
    - Data class lock and unlock methods perform as advertised, and can be reused if other non-RMI remote connection methods are implemented
    - Because Data performs the locking, it is able to first check if the record is a valid one, and throw the exception mentioned in the javadocs, "@exception IOException If the record position is invalid." (Well, I actually changed it to DatabaseException, but at least it does throw an exception as advertised.)
    - lock and unlock method signatures need not be changed
    - Locker class is well encapsulated and has well-defined responsibility, in the sense that it is not coupled with RMI.
    - Locks will be dropped if client disconnects, crashes, etc.
    The disadvantage is that you are maintaining a list of locks in two different classes. However, the lists are different and serve two entirely different purposes, so I don't really think it's a duplication. Can you let me know of any other disadvantages?
    I have heard others mention that locking should not fall within the responsibility of the Data class, but unfortunately, it's already in the class interface, so I don't see any harm in including an actual implementation and making the Data class do what its methods and javadocs say it does. Comments?
    Another question, does RemoteDataImpl need to extend UnicastRemoteObject if it's not being registered with RMIRegistry?
    Thanks so much for any feedback! It makes me better, and hopefully others will find this discussion useful.
    - Nicole.
    You know, Peter, that's a very good question, because the requirements and the javadoc for unlock() do state:
    "If an attempt is made to unlock a record that has not been locked by this connection, then no action is be taken."
    and
    "Ignored if the caller does not have a current lock on the requested record."
    However, my interpretation of these requirements was "if there's no lock on the record, the unlock() method just does nothing instead of throwing a RecordNotLockedException or taking some other action."
    The way my client is written, there will never be an unlock() call without a corresponding lock() call. So, the only way unlock() would be called without lock() is in the case of malicious hacking. You could take the approach that guarding against malicious hacking is a requirement because of the above statements. However, to me, it just seems silly to guard against malicious hacking in an application that doesn't even have a login screen.
    In response to your question, I am changing the javadoc to be more specific about the action of the unlock() method, and I am also documenting the reasons behind my decision in my design document.
    Thanks for raising that very valid concern, and I welcome any further comments.
    - Nicole
    Thanks Sai. I don't think that was really the question I wanted to ask though. I wanted to ask how to actually implement the threading (i.e. make requests threaded in case the RMI server didn't do it for you), but then I learned how to do a search on this forum ( ) so finally gleaned the correct answers which are:
    1) don't do it, and
    2) don't do it.
    I should've known that something that seems that hard is probably not a good idea.
    As for keeping track of client ID's, I decided not to do that. I'm taking the lazy way out and trusting the client. I wrote it; ipso facto, it's trustworthy.
    Thank you, I do appreciate your assistance and the helpful posts of others on this forum.
    Howdy y'all! What a helpful forum!
    As a newbie to RMI, I was wondering if someone could help me with threading the server.
    1) Given that some RMI implementations are pre-threaded, do I need to make server requests explicitly threaded?
    2) With sockets & serialization, threading the server is straightforward, you can just pass the socket to the new thread and the new thread sends results to the client over the socket. But how do you do this with RMI?
    For example, how would I make this method threaded?

    Or am I looking at this all wrong? Any advice would be appreciated. Thank y'all!
    - Nicole