(Not logged on) | Register | Log On

You can subscribe to this discussion group using an RSS feed reader. The Joel on Software Discussion Group

A place to discuss Joel on Software

This community works best when people use their real names. Please register for a free account.

Other Groups:
Joel on Software
Business of Software
Design of Software (CLOSED)
.NET Questions (CLOSED)
TechInterview.org
CityDesk
FogBugz
Fog Creek Copilot


The Old Forum


Your hosts:
Albert D. Kallal
Li-Fan Chen
Stephen Jones

Java - Converting between different packages

I have 2 classes, we will call them Address. Both have the same attributes but are in different packages. I am trying to write a mediator/converter to convert back and forth between them but i am unsure on how to do this in java, if it is possible. This works fine for simple types but complex types have me stumped.

So for example i have:

class Address{
  int number;
  String[] address;
  String suffix;
}

one of these is defined in com.myspace.client and one is defined in com.myspace.server. I have a wsdl that i created in eclipse that represent the functions that the client will call to get info on the server side. the converter will manage the types to get info from the server, then convert them back to the client types. The idea is to keep the server completely separate from any client to achieve total separation, so that in the future only parts of the converter would have to be re-written.

any help is appreciated.
Used_to_be_anon Send private email
Tuesday, November 24, 2009
 
 
package com.myspace.client

public class Address {

  public Address(com.myspace.server.Address address) {
    this.number = address.getNumber();
    ...
  }

}

So just pass one of the Address types into the constructor of the other (and possibly vice-versa) and do the conversion right there.
Steve Moyer Send private email
Tuesday, November 24, 2009
 
 
ok let me be more specific and lets see if that helps to make sure we are on the same page. A few schemas were created in eclipse to define certain types. One of the types is Address, like i described before. A WSDL was created from these schemas and built into a package. From this, the main IMPL class was created which are the WSDL stub calls that the client will use to retrieve information. I have no control over the client other than the fact that it knows what functions are available and thats all the client knows about. It doesnt know nor is it supposed to know anything about the server side.

An example would be a certain function:

public class myengineSOAPImpl implements com.generated.services.myengine_PortType{
public com.general.client.Address getAddress(int id) throws java.rmi.RemoteException{

  Converter convert = new Converter(id);

}
}

where the com.general.client.Address is the package name + class type that it expects to be returned.

My Converter class is to use the argument 'id' and use that number to do whatever it needs to do to get the correct data that i need, in this case an Address..that is, my own Address class back to the converter as a result.

Because its my own definition of Address(with the same attributes) its going to have a different package name. Remember though that the IMPL class expects to be returned its own Address type thats in a different package that i described at the beginning.

So in my converter class how, would i make the appropriate java method calls or casting class to convert my Address class type to the correct IMPL Address class type that it expects?


thanks for the previous response, hopefully i explained it better this time.
Used_to_be_anon Send private email
Tuesday, November 24, 2009
 
 
Use reflection. Iterate declared fields, find matched by name, copy values. Almost trival operation. Repeat for superclasses if required.
Vladimir Dyuzhev Send private email
Tuesday, November 24, 2009
 
 
You won't be able to typecast between the 2 object hierarchies unless they implement a common base Address class or interface.

To reference 2 identically named classes in the same class, one can be imported and the other will need a fully-qualified package.class when referenced, or both could be fully qualified

import client.Address;
public class ServerProxy {
  public Address getAddress(String id) {
    // Retrieve the server version of the Address class
    com.x.y.server.Address serverAddress = dbQuery.findAddress(id);

    // Do stuff to the server side Address
    ...

    // Convert server version to the client-side representation
    AddressConverter converter = new AddressConverter();

    return converter.toClientAddress(serverAddress);
  }
}


If AddressConverter's only responsibility is to convert between the 2 Address classes, then it would have 2 conversion methods, where 1 of the Address classes is fully qualified:

import client.Address;

public class AddressConverter {
    public com.x.y.server.Address toServerAddress(Address clientAddress)

    public Address toClientAddress(com.x.y.server.Address serverAddress)
}
carlos bonilla Send private email
Wednesday, November 25, 2009
 
 
Avoid bi-directional dependencies between packages like a plague, they create "interesting" build failures.
quant dev Send private email
Wednesday, November 25, 2009
 
 
dozer might be useful for this.
JeffCo Send private email
Wednesday, November 25, 2009
 
 
As suggested, have both classes implement an interface:

interface IAddress {
 int getNumber();
 String[] getAddress();
 String getSuffix();
 void setNumber( int number );
 void setAddress( String[] address );
 void setSuffix( String suffix );
}

You can then create a utility method to convert from any implementation of IAddress to any other given implementation:

Class AddressBridge {

 public static void convertAddress( IAddressI sourceAddress,
                                    IAddressI  destAddress ) {
  if ( null != sourceAddress && null != destAddress ) {
  destAddress.setNumber( sourceAddress.getNumber() );
  destAddress.setAddress( sourceAddress.getAddress() );
  destAddress.setPrefix( sourceAddress.getPrefix() );
 }
}

So, the client would take whatever IAdress object it received and the client's version of the object like so:

myspace.client.Address clientAddress = myspace.client.Address();
AddressBridge.convertAddress( someAddress, clientAddress );

That's it.
Matthew Flynn Send private email
Thursday, December 03, 2009
 
 
Sorry, that last bit would be:

myspace.client.Address clientAddress = new
  myspace.client.Address();
AddressBridge.convertAddress( someAddress,
  clientAddress );
Matthew Flynn Send private email
Thursday, December 03, 2009
 
 
The problem is that it forces both classes to be mutable. I prefer my data objects to be as immutable as possible.
quant dev Send private email
Thursday, December 03, 2009
 
 
You could preserve immutability by reducing the common interface to its read-only part and implementing copy constructors in both classes.

Address1(IAddress other)

Address2(IAddress other)
quant dev Send private email
Thursday, December 03, 2009
 
 
thanks all for the input.

what i ended up doing was brute assignment of each part of the structure into whichever package type i needed to convert to.

so if i have package a.address and b.address and both of them have the same members and types i just build locally in my converter class what class i need to convert to and assign values separately all the way down to the primitive types(in the case of a member being a struct).

so if struct is

so if you pass in a com.server.address myAddress...

private static com.client.Address  wsdlAddress = new com.client.Address;

wsdlAddress.zipcode = myAddress.zipcode;
wsdlAddress.name = myAddress.name;
.....
.....

if members are their own struct with the main Address struct then obviously i have to convert that first. After all everything at the lowest level is a primitive and can be copied as such. just takes a bit more code.

gosh i hope that makes sense. i am just getting over a cold.
Used_to_be_anon Send private email
Friday, December 04, 2009
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz