wood burning stoves 2.0*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes Stand alone criteria [B&S] Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCM Java EE 6 Enterprise Architect Exam Guide this week in the OCMJEA forum!
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "Stand alone criteria [B&S]" Watch "Stand alone criteria [B&S]" New topic
Author

Stand alone criteria [B&S]

Jim Janssens
Ranch Hand

Joined: Sep 24, 2004
Posts: 210
The assignment says that for the standalone mode there may be no network traffic, no object serialization etc (there are 3 or 4 points).

Now, I'm using a thin client which connects to the contractor service.

Physical, it exists of the 2 rmi required classes: a remote interface (ContractorService) and an impl class (ContractorServiceImpl) which extends the UnicastRemoteObject and implements ContractorService. The contractor service will do the actual database lookup etc.

For networked mode I do something like this:
ContractorService service = (ContractorService) doRMILookup(SERVICE_NAME);

For standalone mode I do this:
ContractorService service = (ContractorService) doLocalLookup();

The doRMILookup does the actual lookup from the server using its context.

The 'doLocalLookup' method does this:
public Object doLocalLookup() { return new ContractorServiceImpl(); }

So, the standalone mode uses a new instance of the ContractorServiceImpl to work on. But, since it extends UnicastRemoteObject, its constructor will be called also. I checked the source code of this class and it doens't do much really, only load the _stub class (but doesn't do anything with it, at least at creation time).

The only side effect I discovered is that if you remove the _stub class from the jar file and run in standalone mode, it will throw a class not found (because of the constructor of UnicastRemoteObject being called). But I don't think sun is going to delete the _stub class from the jar while testing standalone...

The thing I want to be sure of by doing this is that I do not break any of the network rules. Since it are calls on a normal object, serialization is excluded. Network traffic also because it are ordinary calls to an object. So basicly I don't see anything wrong with it, is this true ?
Dieskun Koper
Ranch Hand

Joined: Aug 15, 2004
Posts: 85
I have the following in my instructions:


Architecturally, this mode must use the database and GUI from the networked form, but must not use the network server code at all.


With this requirement, I would not be surprised if you'd get an auto-failure.
Or can you defend that a class that extends UnicastRemoteObject and throws RemoteExceptions is not a network server class?
Frans Janssen
Ranch Hand

Joined: Dec 29, 2004
Posts: 357
For what it's worth, I am doing the exact same thing as Koen and untill now I never had any doubt I would get away with it.

Sun does not specify what they mean with "the network server code", but I was/am assuming that as long as no (internal) network traffic is generated, I would be safe.

I guess in order to minimize risks, I could solve it by introducing a second adapter class that wraps around the adapter, so I would get the following structures:

REMOTE:
business HAS A adapter2 HAS A (remote) RMIadapter HAS A Data

LOCAL:
business HAS A adapter2 HAS A Data

I think that this does not improve my OO design and violates the "keep it simple" rule, so I think I'll have to sleep another night on whether I want to do this.

Frans.

P.S. I would rather like to hear that someone used a UniCastRemoteObject subclass in StandAlone mode and passed the test. Anyone? :roll:
[ January 14, 2005: Message edited by: Frans Janssen ]

SCJP 1.4, SCJD
Paul Bourdeaux
Ranch Hand

Joined: May 24, 2004
Posts: 783
Personally, I think that using a Remote Object, even through you are not doing any networking still violates the "must". While I agree that it may be simpler for you to code, I think it would be more confusing for a junior developer to maintain your code later - especially when their non networked code starts throwing RemoteExceptions...


“Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning.” - Rich Cook
Jim Janssens
Ranch Hand

Joined: Sep 24, 2004
Posts: 210
Well, it is transparant for the client code if it using it remote or local service. Thats the beauty of it.

Client does this;

Service service = (Service) LookupHelper.getService(serviceName);

It does not know wether its operating on a remote or local version.

About your RemoteException remark:

When using the RemoteServiceImpl (which throws remote's) local or in network mode, you always needs to catch remotes. So it does not change anything to the code or the idea.

The only thing you must explain to the junior programmer is that in local mode a new (local) instance of the RemoteServiceImpl class is created and in network mode an instance of RemoteServiceImpl is acquired using RMI. Thats it.

By using this system you have no code duplication. changes to the 'remote' service also affect the 'local' service.
Ofcourse, another layer of abstraction can solve this...but personally I find no good reasons why to do this in terms of design.

Anyway, I send an email to who2contact . I hope they will answer it.
Paul Bourdeaux
Ranch Hand

Joined: May 24, 2004
Posts: 783
Fair enough... Please post Sun's reply when you get it, as I am sure many others will be interested.

When I designed my networking layer, I added the extra layer of abstraction. I have two interfaces - A DBClient that is the adapter object, and a DBRemote that extends DBClient and Remote. The DBLocalAdapter implements DBClient, and the DBRemoteAdapter implements DBRemote. DBRemoteAdapter simply wraps a DBLocalAdapter. My client then does something to the tune of:

DBConnector is simply a utility class that uses static methods to return either a DBRemoteAdapter (using the Lookup service) or a DBLocalAdapter. If you have read Max's book, then you are probably familiar with this approach.

It took all of five minutes to code the extra class and interface needed, and I think it makes for a more understandable design, especially when diagrammed (for those pesky junior developers). Of course, this is simply a design choice on my part, and as it will not affect performance in any measurable way, I figure it was worth the effort to meet the customer's requirements.
[ January 14, 2005: Message edited by: Paul Bourdeaux ]
Paul Bourdeaux
Ranch Hand

Joined: May 24, 2004
Posts: 783
Koen,

Just to clarify my stance, I don't think there is anything wrong with your design, and I hope it is acceptable to Sun. I just chose to implement my design differently based on my interpretation of the instructions.
Frans Janssen
Ranch Hand

Joined: Dec 29, 2004
Posts: 357
Koen,

I feel the same way, but I am also a bit concerned due to Paul's comments.

So I have decided not to take any chances. After some rethinking since my previous post I came up with an improved solution, which saves me an extra layer:

  • class Data implements the given interface
  • interface DataAdapter: is the same as the one given + Remote
  • class LocalDataAdapter implements DataAdapter and HAS A Data; it never throws a RemoteException
  • class RemoteDataAdapter extends UnicastRemoteObject and implements DataAdapter; it can throw RemoteObject
  • class DataAdapterFactory: can create instances of Local/RemoteDataAdapter


  • My Business layer HAS A DataAdapter as created with the factory, but does not know what kind of instance. It is always prepared to handle a remote exception, even though the actual instance will never throw it.

    The layering is then always the same depth as my original solution:

    Business HAS A DataAdapter HAS A Data.

    The costs are in my case one extra DataAdapter class and the factory class (the factory methods I had upto now integrated into the DataAdapterImpl class I had before).

    After all I think the solution is still quite "nice" in the OO sense and at low cost. I still think my original implementation was better, but I don't want to risk missing a MUST.

    Frans.
    Jim Janssens
    Ranch Hand

    Joined: Sep 24, 2004
    Posts: 210
    Originally posted by Paul Bourdeaux:
    Fair enough... Please post Sun's reply when you get it, as I am sure many others will be interested.

    When I designed my networking layer, I added the extra layer of abstraction. I have two interfaces - A DBClient that is the adapter object, and a DBRemote that extends DBClient and Remote. The DBLocalAdapter implements DBClient, and the DBRemoteAdapter implements DBRemote. DBRemoteAdapter simply wraps a DBLocalAdapter. My client then does something to the tune of:

    DBConnector is simply a utility class that uses static methods to return either a DBRemoteAdapter (using the Lookup service) or a DBLocalAdapter. If you have read Max's book, then you are probably familiar with this approach.

    It took all of five minutes to code the extra class and interface needed, and I think it makes for a more understandable design, especially when diagrammed (for those pesky junior developers). Of course, this is simply a design choice on my part, and as it will not affect performance in any measurable way, I figure it was worth the effort to meet the customer's requirements.

    [ January 14, 2005: Message edited by: Paul Bourdeaux ]


    Ok, thats no problem to implement your solution at all, however I would find it more complex (in design) to be understood by juniors (but thats just a very minor and ignorable point for this assignment). But beside that, it is probably more safer to do (untill I get some answers from sun).

    However, I have a question about this solution; what did you do about the exceptions in your client ? You both catch RemoteException and for example RecordNotFoundException ?

    I assume that your DBClient declares all possible exceptions. Every method will throw atleast a RemoteException and 'find alike' methods will throw beside the RemoteException (for example) also a RecordNotFoundException.

    So for the the 'find on record number method' (this is just an example) it will look like this;

    public int[] find(int recNo) throws RemoteException, RecordNotFoundException

    Your DBLocalAdapter however, only throws the RecrordNotFoundException.
    Your DBRemote and DBRemoteAdapter will probably try { }catch the 'RecordNotFoundExceptions' and alikes (which are thrown by using the DBLocalAdapter) and they will wrap it into a RemoteException.

    So, in your client you would have this:

    DBClient service = SomeHelper.getService(mode);
    try
    {
    service.find(1);
    }catch(RemoteException remoteException) {
    // get and process cause if availble
    }catch(RecordNotFoundException recordNotFoundException ) {
    // process recordNotFoundException}
    }

    is this correct ?
    Daniel Simpson
    Ranch Hand

    Joined: Sep 02, 2004
    Posts: 181
    I've noticed this thread and I wanted to ask a question about this. I've never used RMI before so I'm a newbie at it. Here is my class break down in my suncertify.remote package:

    DataAdapter- interface (throws RemoteException)
    LocalDataAdapter- implements DataAdapter, HAS-A Data object (which implements the required DB interface) but does not throw RemoteExceptions
    DataRemote- interface (implements Remote and DataAdapter)
    RemoteDataAdapter- extends UnicastRemoteObject, implements DataRemote, HAS-A Data object (passed in from the server, every RemoteDataAdapter uses the same Data object)
    FactoryConnector- Local- returns a LocalDataAdapter or Remote- calls

    Please comment on my package structure. I've never done RMI before so any help is greatly appreciated! Also, in question to what you said:
    However, I have a question about this solution; what did you do about the exceptions in your client ? You both catch RemoteException and for example RecordNotFoundException ?
    If my Gui controller catches RemoteExceptions, regardless if the user is in local or remote mode, would I fail because I'm declaring that my methods "throws" a RemoteException and the client is in local mode?
    [ January 15, 2005: Message edited by: Daniel Simpson ]

    SCJP 1.4<br />SCJD 1.4
    peter wooster
    Ranch Hand

    Joined: Jun 13, 2004
    Posts: 1033
    Originally posted by Daniel Simpson:
    If my Gui controller catches RemoteExceptions, regardless if the user is in local or remote mode, would I fail because I'm declaring that my methods "throws" a RemoteException and the client is in local mode?

    [ January 15, 2005: Message edited by: Daniel Simpson ]


    This is one of the reasons that I use that second adapter to convert my DataAdapter back to a DataProxy that has exactly the same interface as the Data class. This way my GUI code never needs to know about RemoteException or IOException, since the DBAccess interface doesn't throw them. My DBAccess interface is exactly as specified by Sun in the instructions. This also means that I can get a factory method to produce a DBAccess instance based on the mode.

    Both Data and DataProxy use the runtime DataException to wrap IOException which includes RemoteException.
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: Stand alone criteria [B&S]