Hello,

Say I have an abstract class Connection to represent some kind of connection that can be executed and then return some kind of result. My problem is that the result returned by each connection varies (String, byte[], some other class, etc...). This results in additional logic that seems like it defeats the point of using inheritance in the first place, because I have to downcast the Connection object just to find out what kind of result it returns.

Below is some psuedo code that demonstrates the problem. Any thoughts? There has gotta be a cleaner way of doing something like this:

class ConnectionExecutor {
    public void execute(Connection connection) {
        // connection.execute();
        
        if (connection instanceof HttpConnection) {
            String result = ((HttpConnection) connection).getResponse();
            // HttpConnection-specific output logic
        }
        else if (connection instanceof DatabaseConnection) {
            Map<String, String> result = ((DatabaseConnection) connection).getResults();
            // DatabaseConnection-specific output logic
        }
    }
}

abstract class Connection {
    // some common connection functionality
}

class HttpConnection extends Connection {
    public String getResponse() {
        // call web service
        // return the string response
    }
}

class DatabaseConnection extends Connection {
    public Map<String, String> getResults() {
        // call database
        // return mapped results
    }
}

Recommended Answers

All 10 Replies

any thoughts?

How about break it down into two classes for HTTP and Database connection executors? This way, it would be more explicit and ensure that users should use different executor for different type of connection?

IMO, the connection executor is not the right entity to handle the result of your execution. IMO, creating handler classes for specific return types (HandlerXxx for every Connection which returns a String etc) would be a much better strategy since the ConnectionExecutor anyways doesn't know which type of connection it is executing. Something like this should get you started (untested):

class ConnectionResult {
    private final Object t;
    public ConnectionResult(Object t) {
        this.t = t;
    }
    public Object get() {
        return t;
    }
}
abstract class Connection {
    public abstract ConnectionResult getResult();
}
class StringConnection extends Connection {
    public ConnectionResult getResult() {
        ConnectionResult<String> result = new ConnectionResult<String>("A");
        return result;
    }
}
interface Handler {
    void handleResult(ConnectionResult result);
}
class StringHandler implements Handler {
    public void handleResult(ConnectionResult result) {
        String strResult = result.get();
    }    
}
class ConnectionExecutor {
    public void execute(Connection connection, Handler handler) {
        handler.handle(connection.getResult());
    }
}

Anyways, I'd recommend stating the original scenario here so that we can suggest better solutions if any.

Thanks for the replies. I had similar thoughts to as what you guys described, but just wasn't quite sure how to implement it.

SOS, it looks like your ConnectionResult class, based on the psuedo code with the <String> is using generics... so would the class definition look more like:

class ConnectionResult<ResultType> {
    private final ResultType t;
    public ConnectionResult(ResultType t) {
        this.t = t;
    }
    public ResultType get() {
        return t;
    }
}

?


Either way, I'll explain the details a little bit more in detail.

Say I have N number of back-end systems, which can be database servers, web servers, etc... The base Connection class will represent a connection to each of these back-end systems, with abstract methods for retrieving xml, csv, binary, etc... responses. This response data is then output to a servlet response output stream.

Hope that helps.

Thanks!

it looks like your ConnectionResult class, based on the psuedo code with the <String> is using generics

I had actually planned on posting a generified solution but it got a bit complicated so I stripped it out for brevity. Anyways, those changes can be made once you get your design is finalized.

Say I have N number of back-end systems, which can be database servers, web servers, etc... The base Connection class will represent a connection to each of these back-end systems, with abstract methods for retrieving xml, csv, binary, etc... responses. This response data is then output to a servlet response output stream.

I'm a bit wary of this abstraction you are proposing here. The connection class you talk about already exists. I think there is a reason why the existing connections are not grouped into a single subclass. The functionality offered by each one of them is so varied that abstracting it provides little or no benefit. There are two levels of abstraction which we are talking about here:
- Connection abstraction
- view abstraction (ability to present data in different formats)

The reason why you are finding it difficult to visualize the solution is because you are missing an important layer; the data access layer. Connection is something physical and view is something abstract which can and will vary. The way/logic a data is retrieved from a connection is very specific. For e.g. if you have a JDBC connection, you are dealing with result sets. If you have a TCP connection, you are dealing with ad-hoc string/binary data.

The data access layer here is responsible for reading the data from the underlying datastore and converting it to an object fit for general consumption. E.g. reading the person table from a database and making the DAO method return a Person object. The speciality of the DAO pattern is that the client can continue using the data access service irrespective of the underlying datastore technology. An e.g.

public interface PersonDao {
	public Person getPersonForId(String id);
}
public class PersonDaoJdbcImpl implements PersonDao {
	public Person getPersonForId(String id) {
		// use jdbc connection to read the resultset and create a person object
	}
}
public class PersonDaoXmlImpl implements PersonDao {
	public Person getPersonForId(String id) {
		// read the data from a XML flat file and create a person object from it
	}
}
// the class involved when the user performs search
public class SearchServlet extends HttpServlet {
	protected void doGet(HttpServletRequest req, HttpServletResponse res)
		throws IOException, ServletException {
		PersonDao dao = PersonDaoFactory.getJdbcDao();
		Person p = dao.getPeronForId("ID123");
		Renderer renderer = new PersonDataXmlViewRenderer(p, res);
	}
}

The point here being, abstract the way data is extracted and use the same data for rendering your response in the required format. Another thing worth noting is that there is a lot of boilerplate code involved when creating an abstraction of this sort. If you can, try using some sort of framework which takes care of the "this is so obvious" stuff. BTW, using a framework like REST framework like RESTlet or Spring Framework REST support would actually reduce your job since it provides a lot of utility classes for creating custom content-type responses like XML, CSV etc.

Thanks for the reply. Going by your example, do you think it's an acceptable design to delegate the rendering to another class by simply passing in the response object? That was basically the same conclusion I came to, but it seemed a little "backwards" to me.

I'm already using Spring for IoC, so the Servlet that would be doing the rendering first calls out to a bean that then returns a custom implementation of a Response class, which contains a getter to retrieve the content type and data of the response (which can vary by String, byte[], etc...). Would it be more suitable to instead delegate the responsibility of rendering the Response's data by passing in the HttpServletReponse to it with some kind of renderContent(HttpServletResponse response) method?

Could you explain in more detail how 3rd party frameworks could help? Not quite sure I follow.

Thanks!

but it seemed a little "backwards" to me.

Backwards? IMO, delegating to an appropriate class for performing the different functions of a system is far more logical than creating a "god" class which is responsible for everything (retrieving data, setting up responses etc.).

Could you explain in more detail how 3rd party frameworks could help? Not quite sure I follow.

Is this is web application or a RESTful API you have created for external consumption? If the former, you can use the Spring MVC framework which provides an abstraction over the basic servlet infrastructure. If the latter, using the RESTful framework offered by Spring would again significantly cut down your code. I haven't worked extensively with either of those so the Spring documentation would be your best friend here; esp the Spring MVC and Spring REST framework part.

I agree with what you mean about avoiding the creation of a "god" class. The part that seems backwards to me is passing a HttpServletResponse object into some class and then letting it have free reign over what it does with it at that point. It does makes sense abstraction wise though, because it lets each connection render its content into the HttpServletResponse accordingly.

I've thought about this a bunch more, and still haven't came up with any kind of design/solution I like. I kind of like the DAO design, but the way the connection implementations will be used in my application, they are essentially just proxying the data from various back-ends into a standard response envelope (which varies between XML, CSV, JSON, byte[], etc...) as a servlet response which will then be consumed by client-side AJAX requests.

Are there any ways to possibly extend the DAO pattern to achieve this? Or perhaps a different approach all together?

Thanks again for your help!

One other bit of background is that the data being proxy'd will not be mapped to any kind of Java object along the way. The only way the data might be manipulated between the back-end and the output from my servlet is that it might be normalized into a consistent response envelope.

The problem is still to represent http web services + database back-ends through some kind of "Connection" interface, and then have a common way of extracting the response data aftewards (xml, json, csv, binary, etc...). As I see it, the 2 groups of response types are String or Binary... still struggling with trying to figure out a solid design for this.

Good design hides the implementation complexity, it doesn't do away with the complexity. When you say you need different representations (csv, xml, json etc.), the class creating the representation *needs* to know about the structure of the data to be converted, be it plain XML or a Java object. You say there won't be any Java object along the way. So how do you propose to retrieve data from a database/web-service? How will the resulting data look?

Post a sample code which shows "how" you'd like to see the code or a code sample for a fictional use case like getting a list of all employees using a web-service/database/socket connection. Also make sure you consider the entire flow instead of just posting your connection classes.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.