Derby
  1. Derby
  2. DERBY-289

Enable code sharing between Derby client and engine

    Details

    • Type: Improvement Improvement
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: 10.0.2.0, 10.0.2.1, 10.0.2.2, 10.1.1.0
    • Fix Version/s: None
    • Component/s: Network Client
    • Labels:
      None
    • Environment:
      N/A
    • Urgency:
      Low

      Description

      Right now, there is no way for the Derby network client to share code with the Derby engine. We should have a separate jar file, e.g. derby_common.jar, that contains shared code and is used by both the client and the engine.

      1. DERBY-289.diff
        188 kB
        David Van Couvering

        Issue Links

          Activity

          Hide
          David Van Couvering added a comment -

          Can't fix this until DERBY-289 is resolved, as there is no place to put shared code.

          Show
          David Van Couvering added a comment - Can't fix this until DERBY-289 is resolved, as there is no place to put shared code.
          Hide
          David Van Couvering added a comment -

          I would like to modify the network client to use localized messages.
          However, the right way to do this is using message ids, and these
          message ids probably should be based on SQL states, just as with
          the embedded code. We should also take advantage of the existing
          infrastructure for properly loading and composing message strings,
          rather than build a duplicate infrastructure for the client code.

          As a first step towards fixing exception handling in the client, I am
          therefore planning on working on creating a common package hierarchy
          that contains code that can be shared across client and server code.

          Here are the steps I am planning on taking. Your comments are most welcome.

          • Create a new top-level directory under trunk/java called "common". All
            packages under this directory would have the prefix org.apache.derby.common
          • Refactor the existing service classes under org.apache.derby.iapi.services
            and org.apache.derby.impl.services into common code and engine-specific
            code. I would do the minimum possible so that the error and i18n
            services can move over to the common directory. I do not intend to move
            over other services even if they could be considered common; I feel this
            work should be done only as needed.

          At first glance, the packages impacted by this refactoring effort would be:
          org.apache.derby.iapi.services.Monitor
          org.apache.derby.impl.services.Monitor
          org.apache.derby.iapi.services.i18n
          org.apache.derby.iapi.error

          There may be other packages impacted due to dependencies I have yet to
          discover.

          I have noticed that some of the code seems to have some fairly strong
          ties to the engine environment. I hope to solve this by
          splitting some classes into a generic superclass in the common
          hierarchy and a subclass in the engine hierarchy.

          • In terms of the build environment, the easy approach, and the approach
            that matches what already exists, would suggest creating a new jar file,
            derbyclient.jar.

          However, we already have a large number of jar files, and adding one
          more I feel is going in the wrong direction. I would like to better
          understand the motivation for having multiple jar files when I think
          we could do with two: one for engine/server-side code and one for
          client code, e.g.

          derby.jar
          derbyclient.jar
          <locale_jar_files>

          Comments on this are most appreciated.

          Thanks,

          David

          Show
          David Van Couvering added a comment - I would like to modify the network client to use localized messages. However, the right way to do this is using message ids, and these message ids probably should be based on SQL states, just as with the embedded code. We should also take advantage of the existing infrastructure for properly loading and composing message strings, rather than build a duplicate infrastructure for the client code. As a first step towards fixing exception handling in the client, I am therefore planning on working on creating a common package hierarchy that contains code that can be shared across client and server code. Here are the steps I am planning on taking. Your comments are most welcome. Create a new top-level directory under trunk/java called "common". All packages under this directory would have the prefix org.apache.derby.common Refactor the existing service classes under org.apache.derby.iapi.services and org.apache.derby.impl.services into common code and engine-specific code. I would do the minimum possible so that the error and i18n services can move over to the common directory. I do not intend to move over other services even if they could be considered common; I feel this work should be done only as needed. At first glance, the packages impacted by this refactoring effort would be: org.apache.derby.iapi.services.Monitor org.apache.derby.impl.services.Monitor org.apache.derby.iapi.services.i18n org.apache.derby.iapi.error There may be other packages impacted due to dependencies I have yet to discover. I have noticed that some of the code seems to have some fairly strong ties to the engine environment. I hope to solve this by splitting some classes into a generic superclass in the common hierarchy and a subclass in the engine hierarchy. In terms of the build environment, the easy approach, and the approach that matches what already exists, would suggest creating a new jar file, derbyclient.jar. However, we already have a large number of jar files, and adding one more I feel is going in the wrong direction. I would like to better understand the motivation for having multiple jar files when I think we could do with two: one for engine/server-side code and one for client code, e.g. derby.jar derbyclient.jar <locale_jar_files> Comments on this are most appreciated. Thanks, David
          Hide
          David Van Couvering added a comment -

          Internationalizing error messages can't be done without common code framework without a lot of code duplication.

          Show
          David Van Couvering added a comment - Internationalizing error messages can't be done without common code framework without a lot of code duplication.
          Hide
          Daniel John Debrunner added a comment -

          I think any shared solution needs to handle mixing of client and server/engine versions. E.g. assuming shared code is added in 10.2, an application could be using a local 10.2 derby engine but using a 10.3 client to talk to a remote derby engine, all from the same JVM. Apart from mismatched classes, it's also hard to guarantee which common code is loaded, the 10.2 or the 10.3, usually depends on class path order. Thus you may have handle the common code be at a lower or higher level than expected.

          As for a single server side jar, that forces the network server overhead on simple embedded users, and may add a security concern they don't want to have, basically code that listens on a network port. Even having the code in the jar may of concern, even if they never start it.

          Show
          Daniel John Debrunner added a comment - I think any shared solution needs to handle mixing of client and server/engine versions. E.g. assuming shared code is added in 10.2, an application could be using a local 10.2 derby engine but using a 10.3 client to talk to a remote derby engine, all from the same JVM. Apart from mismatched classes, it's also hard to guarantee which common code is loaded, the 10.2 or the 10.3, usually depends on class path order. Thus you may have handle the common code be at a lower or higher level than expected. As for a single server side jar, that forces the network server overhead on simple embedded users, and may add a security concern they don't want to have, basically code that listens on a network port. Even having the code in the jar may of concern, even if they never start it.
          Hide
          David Van Couvering added a comment -

          Thanks for your comments, Dan.

          Can you explain to me how a classloader can load a 10.2 shared class for the client code and a 10.3 shared class for the server? Isn't the classpath the same, so you end up picking up the same class either way? Assuming this is possible, is this something we actually want to try and handle? I could see doing two versions under two different classloaders, with different classpaths, to support online upgrade – but within the same Derby system/classloader? It seems if anything, I should catch a version mismatch and throw an exception, but do we really want to try and make this work? Can you give me a scenario where this is useful/desirable?

          Regarding the jar files, I see your point: jars are units of security. Why expose an embedded user to the risks of network code unnecessarily. I'll rescind my suggestion.

          Thanks,

          David

          Show
          David Van Couvering added a comment - Thanks for your comments, Dan. Can you explain to me how a classloader can load a 10.2 shared class for the client code and a 10.3 shared class for the server? Isn't the classpath the same, so you end up picking up the same class either way? Assuming this is possible, is this something we actually want to try and handle? I could see doing two versions under two different classloaders, with different classpaths, to support online upgrade – but within the same Derby system/classloader? It seems if anything, I should catch a version mismatch and throw an exception, but do we really want to try and make this work? Can you give me a scenario where this is useful/desirable? Regarding the jar files, I see your point: jars are units of security. Why expose an embedded user to the risks of network code unnecessarily. I'll rescind my suggestion. Thanks, David
          Hide
          Daniel John Debrunner added a comment -

          I meant either the 10.2 version or the 10.3 version would be loaded, only one. And the code has to deal with it.
          As it being useful, I don't know, but it is supported today because the client jar and the engine jar are totally independent,
          thus you would be removing this option, or enforcing the requirement that within a same JVM the client and engine must be in sync.
          Maybe that's acceptable, but it does need to be discussed or addressed, not just assume the client and the engine will be in sync.

          Show
          Daniel John Debrunner added a comment - I meant either the 10.2 version or the 10.3 version would be loaded, only one. And the code has to deal with it. As it being useful, I don't know, but it is supported today because the client jar and the engine jar are totally independent, thus you would be removing this option, or enforcing the requirement that within a same JVM the client and engine must be in sync. Maybe that's acceptable, but it does need to be discussed or addressed, not just assume the client and the engine will be in sync.
          Hide
          David Van Couvering added a comment -

          Ok, got it.

          I think it's reasonable to require that all the jars in the classpath should be the same version. That said, configuration mistakes happen, and I agree the code should detect it and raise an error if there is a version mismatch. Should I put this (and/or the whole proposal) up for a vote?

          Show
          David Van Couvering added a comment - Ok, got it. I think it's reasonable to require that all the jars in the classpath should be the same version. That said, configuration mistakes happen, and I agree the code should detect it and raise an error if there is a version mismatch. Should I put this (and/or the whole proposal) up for a vote?
          Hide
          Daniel John Debrunner added a comment -

          In case it's not clear, this is the type of situation I'm talking about.

          Application A is a client server application and requires Derby client 10.2

          Application B is a local embedded Derby application and requires Derby engine 10.3

          Now I want to run a client to A and B in the same JVM for some reason, maybe portlets, maybe multiple applications
          in the same app server, maybe application B requires access to application A.

          This would be supported with the current model, complete flexibility because the code bases are separate.

          So do we want to lose this flexibility, or support it with the shared code model?

          Some side history, we did do some work at IBM for Cloudscape prior to open sourcing that ensured that the tools (ij mainly) did not have to be at the same version as the engine, basically by ensuring there was no code in common. This was a request from our customers.

          Show
          Daniel John Debrunner added a comment - In case it's not clear, this is the type of situation I'm talking about. Application A is a client server application and requires Derby client 10.2 Application B is a local embedded Derby application and requires Derby engine 10.3 Now I want to run a client to A and B in the same JVM for some reason, maybe portlets, maybe multiple applications in the same app server, maybe application B requires access to application A. This would be supported with the current model, complete flexibility because the code bases are separate. So do we want to lose this flexibility, or support it with the shared code model? Some side history, we did do some work at IBM for Cloudscape prior to open sourcing that ensured that the tools (ij mainly) did not have to be at the same version as the engine, basically by ensuring there was no code in common. This was a request from our customers.
          Hide
          David Van Couvering added a comment -

          OK. I think we need to solve this. It seems wrong to me to make it so we can't share code across client and server because of, what seems to me anyway, an edge case.

          I have some ideas, I'm going to do some playing around and prototyping, and I'll get back to you all about this.

          David

          Show
          David Van Couvering added a comment - OK. I think we need to solve this. It seems wrong to me to make it so we can't share code across client and server because of, what seems to me anyway, an edge case. I have some ideas, I'm going to do some playing around and prototyping, and I'll get back to you all about this. David
          Hide
          Rick Hillegas added a comment -

          I confess I'm still puzzled. It seems to me there may be two separate issues here: 1) the interoperability of different derby versions across a network and 2) the coherence of derby code running in a single VM. I'm all in favor of interoperability. But mixing and matching derby versions in the same VM puzzles me. I wonder whether we are talking about an edge case here. Is that edge case worth not sharing utility libraries across derby?

          Show
          Rick Hillegas added a comment - I confess I'm still puzzled. It seems to me there may be two separate issues here: 1) the interoperability of different derby versions across a network and 2) the coherence of derby code running in a single VM. I'm all in favor of interoperability. But mixing and matching derby versions in the same VM puzzles me. I wonder whether we are talking about an edge case here. Is that edge case worth not sharing utility libraries across derby?
          Hide
          Kathey Marsden added a comment -

          As for the mixed versions, I would like to understand how we would recommend upgrading in a situation where the jvm in question has both server and client to talk to remote servers in a failover situation or whatever. So I have 100 nodes each with client and server talking to each other.

          Typically you might tell me.

          1) upgrade all your servers.
          2) upgrade your clients and application to use the new functionality.

          So at least for some period of time there would be a mix of versions. Theoretically if we guarantee full backward/forward compatibility, I could use my old application with the new client for some period of time, but that would be a burdon because I would have to test my old application with the new client and who wants to spend time on that.

          So how would I upgrade in this scenario?

          Show
          Kathey Marsden added a comment - As for the mixed versions, I would like to understand how we would recommend upgrading in a situation where the jvm in question has both server and client to talk to remote servers in a failover situation or whatever. So I have 100 nodes each with client and server talking to each other. Typically you might tell me. 1) upgrade all your servers. 2) upgrade your clients and application to use the new functionality. So at least for some period of time there would be a mix of versions. Theoretically if we guarantee full backward/forward compatibility, I could use my old application with the new client for some period of time, but that would be a burdon because I would have to test my old application with the new client and who wants to spend time on that. So how would I upgrade in this scenario?
          Hide
          Kathey Marsden added a comment -

          The biggest concern for me is upgrade in server configurations where both the client and server are in the classpath. See the upgrade scenario in the previous comment.

          I think taking away the ability to mix versions and requiring users to judiciously use ClassLoaders in order to upgrade is not reasonable, especially when the reason for the change cannot be explained in terms of any functionality improvement.

          I think

          • We need to allow mixing of client and server versions, both on a protocol level and in the same classpath.
          • We should keep jar file growth commensurate with functionality improvement.
          • We should try to avoid asking every user in the world to change their classpath.

          For code sharing now, I think constants would be a great place to start since they get compiled out.

          For other code, it seems to me that we will need either some stable internal API (hard to manage) or some build trick to create a client jar with a separate package namespace for the common code (weird because the classes in the stack traces would be a little different than the actual code). That's all I have in the way of ideas, but know I really don't want to see us loose the ability to mix client and server versions.

          Show
          Kathey Marsden added a comment - The biggest concern for me is upgrade in server configurations where both the client and server are in the classpath. See the upgrade scenario in the previous comment. I think taking away the ability to mix versions and requiring users to judiciously use ClassLoaders in order to upgrade is not reasonable, especially when the reason for the change cannot be explained in terms of any functionality improvement. I think We need to allow mixing of client and server versions, both on a protocol level and in the same classpath. We should keep jar file growth commensurate with functionality improvement. We should try to avoid asking every user in the world to change their classpath. For code sharing now, I think constants would be a great place to start since they get compiled out. For other code, it seems to me that we will need either some stable internal API (hard to manage) or some build trick to create a client jar with a separate package namespace for the common code (weird because the classes in the stack traces would be a little different than the actual code). That's all I have in the way of ideas, but know I really don't want to see us loose the ability to mix client and server versions.
          Hide
          Rick Hillegas added a comment -

          The build trick would be fairly easy to implement. It would, however, become a speed bump for new developers. We could slap a big comment in BUILDING.txt. Any other suggestions about how to avoid confusing the unwary?

          Show
          Rick Hillegas added a comment - The build trick would be fairly easy to implement. It would, however, become a speed bump for new developers. We could slap a big comment in BUILDING.txt. Any other suggestions about how to avoid confusing the unwary?
          Hide
          Satheesh Bandaram added a comment -

          Thanks, Kathey... I think we may be able to use JAR sealing mechanism to enforce consistant version of the classes are used. We already use sealing for the server JAR, so a similar mechanism could work for the client. I haven't actually used sealing yet, so don't know if there are any issues in doing so

          Show
          Satheesh Bandaram added a comment - Thanks, Kathey... I think we may be able to use JAR sealing mechanism to enforce consistant version of the classes are used. We already use sealing for the server JAR, so a similar mechanism could work for the client. I haven't actually used sealing yet, so don't know if there are any issues in doing so
          Hide
          Rick Hillegas added a comment -

          I'm unclear on how jar file sealing helps us here. According to http://java.sun.com/developer/JDCTechTips/2001/tt0130.html, jar file sealing is a mechanism to prevent hackers from subverting package protection by creating new classes in your packages. Jar file sealing causes an error to be raised if someone tries to load a class that isn't in your jar file but is masquerading in your package. I don't think this will help us out if we have two copies of the same class, an uprev copy in one jar file and a downrev copy in the other jar file. Jar file sealing doesn't seem to address the problem of classes from other packages referencing your common code. I think that even with jar file sealing you will continue to see the behavior you don't like: the first copy of the class on the CLASSPATH is the one that will be loaded.

          Show
          Rick Hillegas added a comment - I'm unclear on how jar file sealing helps us here. According to http://java.sun.com/developer/JDCTechTips/2001/tt0130.html , jar file sealing is a mechanism to prevent hackers from subverting package protection by creating new classes in your packages. Jar file sealing causes an error to be raised if someone tries to load a class that isn't in your jar file but is masquerading in your package. I don't think this will help us out if we have two copies of the same class, an uprev copy in one jar file and a downrev copy in the other jar file. Jar file sealing doesn't seem to address the problem of classes from other packages referencing your common code. I think that even with jar file sealing you will continue to see the behavior you don't like: the first copy of the class on the CLASSPATH is the one that will be loaded.
          Hide
          Kathey Marsden added a comment -

          David Van Couvering wrote:

          >I'm uncomfortable with the "build trick" – it feels like a hack. Let's
          >think about this some more.
          >
          I agree. I don't like either one of my ideas much to tell you the truth and stick by original assessment of hard and weird respecively. I threw them out there in the hopes that someone would counter with something better #. Satheesh's sealed jar idea sounds much more promising to me if it pans out. If not, maybe others have some good ideas on how to share code and still allow version mixing of the jar files.

          Show
          Kathey Marsden added a comment - David Van Couvering wrote: >I'm uncomfortable with the "build trick" – it feels like a hack. Let's >think about this some more. > I agree. I don't like either one of my ideas much to tell you the truth and stick by original assessment of hard and weird respecively. I threw them out there in the hopes that someone would counter with something better # . Satheesh's sealed jar idea sounds much more promising to me if it pans out. If not, maybe others have some good ideas on how to share code and still allow version mixing of the jar files.
          Hide
          John H. Embretsen added a comment -

          Regarding issues with jar sealing:
          The DERBY-496 issue (http://issues.apache.org/jira/browse/DERBY-496) is certainly related to jar sealing. A sealed package exists in multiple jar files, causing a SecurityException, which in turn causes a specific test to fail (on some systems) unless the ordering of jar-files in the CLASSPATH is compensating for this. I don't know how relevant it is to this discussion, though...

          Show
          John H. Embretsen added a comment - Regarding issues with jar sealing: The DERBY-496 issue ( http://issues.apache.org/jira/browse/DERBY-496 ) is certainly related to jar sealing. A sealed package exists in multiple jar files, causing a SecurityException, which in turn causes a specific test to fail (on some systems) unless the ordering of jar-files in the CLASSPATH is compensating for this. I don't know how relevant it is to this discussion, though...
          Hide
          Rick Hillegas added a comment -

          Please ignore this dummy edit. I want to see if this triggers JIRA mail.

          Show
          Rick Hillegas added a comment - Please ignore this dummy edit. I want to see if this triggers JIRA mail.
          Hide
          Rick Hillegas added a comment -

          Please also ignore this dummy comment, again added to see if it triggers JIRA mail.

          Show
          Rick Hillegas added a comment - Please also ignore this dummy comment, again added to see if it triggers JIRA mail.
          Hide
          David Van Couvering added a comment -

          PROPOSAL FOR SHARING CODE IN DERBY

          Here are the outlines of how we plan to share code in Derby. This first
          version is a high-level description of the approach. After incorporating
          your feedback and piloting with the internationalization code, I will write
          up a more detailed proposal.

          PRINCIPLES AND REQUIREMENTS

          It's important to understand and agree upon the principles and requirements
          of this feature

          • Allow sharing of common code across all parts of the Derby codeline,
            in particular between the network client and the engine.
          • Make it easy to code agains common components (avoid onerous overhead)
          • Support the following binary compatibility rules. This is based
            off of the compatibility rules defined for the Apache Portable
            Runtime (APR) project (see http://apr.apache.org/versioning.html):
          • compatibility guaranteed against later versions until
            the major version number changes (e.g. a 10.1 consumer will
            work with with 10.2 common classes, but a 10.2 consumer is
            not guaranteed to work with 11.0 common classes).
          • compatibility guaranteed for all previous patch versions
            (e.g. a 10.1.2 consumer will work with 10.1.1 common classes).
          • compatibility will be strongly encouraged but not guaranteed
            against previous minor versions (e.g. a 10.2 consumer works
            with 10.1 common classes, but a 10.3 consumer has a hard
            dependency on new methods, it can not work with 10.2
            common classes).
          • no expectation for compatibility for previous major versions
            (e.g. 10.1 is not guaranteed to work with 11.0).
          • Support for both direct creation of classes and pluggable infrastructure
            where this is needed. Some common classes are very simple, and not
            everything should require a pluggable infrastructure.

          IMPLEMENTATION PLAN

          • Create a new directory java/common
          • Create a new package directory under common, org/apache/derby/common
          • Classes created within the common package hierarchy needs to follow the
            guidelines for common components as described below
          • Provide a CommonVersion helper class (described further below)
            that allows consumers to detect what version of the common components
            is available and determine whether the version is compatible.
          • Modify the build script to create a new jar file, derby-common.jar,
            which contains all the common classes.
          • Update the documentation to describe the need for this new jar file
            in the classpath/ext directory/etc.

          COMMON CLASS CODING GUIDELINES

          These guidelines are for any classes in the common package with
          public methods. These guidelines should actually be applied to major
          releases as well, as much as possible, but compatibility is not
          required between major releases.

          Compatibility will be tested with a new suite of compatibility
          tests (currently being devised by Rick Hillegas)

          • Class names and package names should not change between patch or
            minor releases.
          • Existing public method names, method signatures, and public field
            names should not change between patch or minor releases.
          • Existing public fields or methods should not be removed between patch
            or minor releases.
          • Although the code of existing methods can change, the defined behavior,
            in terms of semantics and observable effects, should not change
            between patch and minor releases.
          • New classes, packages, public fields and methods can be added between
            minor releases, but not between patch releases, as this would break
            forward-compatibility for patch releases.

          VERSION DETECTION

          The Version class will be defined as a common class and is used to
          define a version and check for compatibility between a consumer and
          the common package. Here is a first pass at the methods on this class.

          public class Version

          { /** * return the String representation of the version of the * common package */ static Version getCommonVersion() /** * Create a version object. For 10.1.2 you would say * <code>new Version(10, 1, 2)</code> */ public Version(int major, int minor, int patch) int getMajor() int getMinor() int getPatch() /** * Check to see if a consumer is compatible with the common package. * This method should be called when the consumer is being initialized, * and an exception should be thrown if they are not compatible. * * If the consumer version is older than or the same as the common * package version, we have all the knowledge we need to determine * compatibility. * * If the consumer is newer than the common package, then we need * to check for forward compatibility (e.g. to see if the older common * package can work with the newer consumer). If only the patch * versions differ, then by our compatibility rules the two versions * must be compatible. If the major or minor versions differ then we * use the firstIncompatibleVersion parameter to determine forward * compatibility. If firstIncompatibleVersion is null then we * assume full forward compatibility (the consumer is saying "I can * work with anything"). * * * Usage example: * * checkCommonCompatibility(new Version(10, 1, 2), null); * checkCommonCompatibility(new Version(11, 0, 1), new Version(10, 9, 0) */ boolean checkCommonCompatibility(Version consumer, Version firstIncompatibleVersion) }
          Show
          David Van Couvering added a comment - PROPOSAL FOR SHARING CODE IN DERBY Here are the outlines of how we plan to share code in Derby. This first version is a high-level description of the approach. After incorporating your feedback and piloting with the internationalization code, I will write up a more detailed proposal. PRINCIPLES AND REQUIREMENTS It's important to understand and agree upon the principles and requirements of this feature Allow sharing of common code across all parts of the Derby codeline, in particular between the network client and the engine. Make it easy to code agains common components (avoid onerous overhead) Support the following binary compatibility rules. This is based off of the compatibility rules defined for the Apache Portable Runtime (APR) project (see http://apr.apache.org/versioning.html): compatibility guaranteed against later versions until the major version number changes (e.g. a 10.1 consumer will work with with 10.2 common classes, but a 10.2 consumer is not guaranteed to work with 11.0 common classes). compatibility guaranteed for all previous patch versions (e.g. a 10.1.2 consumer will work with 10.1.1 common classes). compatibility will be strongly encouraged but not guaranteed against previous minor versions (e.g. a 10.2 consumer works with 10.1 common classes, but a 10.3 consumer has a hard dependency on new methods, it can not work with 10.2 common classes). no expectation for compatibility for previous major versions (e.g. 10.1 is not guaranteed to work with 11.0). Support for both direct creation of classes and pluggable infrastructure where this is needed. Some common classes are very simple, and not everything should require a pluggable infrastructure. IMPLEMENTATION PLAN Create a new directory java/common Create a new package directory under common, org/apache/derby/common Classes created within the common package hierarchy needs to follow the guidelines for common components as described below Provide a CommonVersion helper class (described further below) that allows consumers to detect what version of the common components is available and determine whether the version is compatible. Modify the build script to create a new jar file, derby-common.jar, which contains all the common classes. Update the documentation to describe the need for this new jar file in the classpath/ext directory/etc. COMMON CLASS CODING GUIDELINES These guidelines are for any classes in the common package with public methods. These guidelines should actually be applied to major releases as well, as much as possible, but compatibility is not required between major releases. Compatibility will be tested with a new suite of compatibility tests (currently being devised by Rick Hillegas) Class names and package names should not change between patch or minor releases. Existing public method names, method signatures, and public field names should not change between patch or minor releases. Existing public fields or methods should not be removed between patch or minor releases. Although the code of existing methods can change, the defined behavior, in terms of semantics and observable effects, should not change between patch and minor releases. New classes, packages, public fields and methods can be added between minor releases, but not between patch releases, as this would break forward-compatibility for patch releases. VERSION DETECTION The Version class will be defined as a common class and is used to define a version and check for compatibility between a consumer and the common package. Here is a first pass at the methods on this class. public class Version { /** * return the String representation of the version of the * common package */ static Version getCommonVersion() /** * Create a version object. For 10.1.2 you would say * <code>new Version(10, 1, 2)</code> */ public Version(int major, int minor, int patch) int getMajor() int getMinor() int getPatch() /** * Check to see if a consumer is compatible with the common package. * This method should be called when the consumer is being initialized, * and an exception should be thrown if they are not compatible. * * If the consumer version is older than or the same as the common * package version, we have all the knowledge we need to determine * compatibility. * * If the consumer is newer than the common package, then we need * to check for forward compatibility (e.g. to see if the older common * package can work with the newer consumer). If only the patch * versions differ, then by our compatibility rules the two versions * must be compatible. If the major or minor versions differ then we * use the firstIncompatibleVersion parameter to determine forward * compatibility. If firstIncompatibleVersion is null then we * assume full forward compatibility (the consumer is saying "I can * work with anything"). * * * Usage example: * * checkCommonCompatibility(new Version(10, 1, 2), null); * checkCommonCompatibility(new Version(11, 0, 1), new Version(10, 9, 0) */ boolean checkCommonCompatibility(Version consumer, Version firstIncompatibleVersion) }
          Hide
          David Van Couvering added a comment -

          Discussion of the above proposal can be found on this email thread:

          http://tinyurl.com/bqvp9

          Show
          David Van Couvering added a comment - Discussion of the above proposal can be found on this email thread: http://tinyurl.com/bqvp9
          Hide
          David Van Couvering added a comment -

          Hi, all. Here is the proposed patch that provides the framework for code sharing. I was thinking folks could look at it and discuss, and then once issues have (hopefully) been worked out, we can have a vote.

          When you apply these changes, you need to manually create an empty master file master/FeatureManagement.out

          Summary of changes:

          • Created new top-level source directory trunk/java/common
          • common/org/apache/derby/common/package.html has a full description of the framework and the guidelines around it. This is an updated version of the policy as we worked out on the Wiki. The intention is that this becomes the official guidelines (and gets updated as needed) once we vote on this and it gets checked in
          • Created some utilities for i18n and error handling that both the engine and network client make use of
          • Created a new SQLException class for the client, SQLException2, which makes use of the common framework. I did this rather than modify the existing class because I wanted a well-structured way to migrate exception code over incrementally.
          • Relocated iapi.services.sanity from the engine to the common area, since it's shared by all (there are more opportunities like this, but this seemed like the simplest example)
          • Moved a few messages from the engine's messages_en.properties under the engine directory to common-messages_en.properties under the common directory. Note that I did not at this time move all the translations over. This is a tedious manual job and I am going to write a tool to do this automatically once all the messages are relocated (or we are ready for a release, whichever comes first).
          • Note that I did NOT move SQLState from iapi.reference at this time. What do you all think – should this be relocated at some point, since it is shared code? It's irrelevant at runtime since it's a class that is simply constants, so it doesn't even get included at runtime. Also
          • Created some unit tests for the feature management aspects of the common framework under tests/common. These are written as JUnit tests. They can be relocated at some point if we identify a single area for new JUnit tests
          • Modified the build to build the common code. I noticed that the build infrastructure automatically picked up common code that the various jar files depended on for derby.jar, derbytools.jar and derbynet.jar. This did not appear to be the case for the client jar, so I modified the derbyclientjar build target to add the common classes

          This passes derbyall. The new unit tests for the common framework are not included in derbyall as they can only be run against the classes directory, not against jar files. This is because the unit tests depend on two "shared component" jar files, and my classloader can't seem to find the classes inside them when they are embedded inside another jar file (e.g. derbyTesting.jar). They need to be jar files because they are two different versions of the same component and they need to be sealed. An alternative approach is to keep them outside of derbyTesting but I was loathe to add the requirement for two more jar files in the classpath to run derbyall.

          svn status output:

          M tools\ant\properties\dirs.properties
          M java\tools\org\apache\derby\impl\tools\sysinfo\Main.java
          M java\engine\org\apache\derby\impl\services\monitor\BaseMonitor.java
          M java\engine\org\apache\derby\iapi\services\i18n\BundleFinder.java
          M java\engine\org\apache\derby\iapi\services\i18n\MessageService.java
          M java\engine\org\apache\derby\iapi\services\sanity\SanityManager.java
          D java\engine\org\apache\derby\iapi\services\sanity\SanityState.tmpl
          M java\engine\org\apache\derby\iapi\services\sanity\AssertFailure.java
          M java\engine\org\apache\derby\iapi\error\StandardException.java
          M java\engine\org\apache\derby\iapi\error\ExceptionSeverity.java
          M java\engine\org\apache\derby\iapi\reference\SQLState.java
          M java\engine\org\apache\derby\loc\messages_de_DE.properties
          M java\engine\org\apache\derby\loc\messages_zh_CN.properties
          M java\engine\org\apache\derby\loc\messages_en.properties
          M java\engine\org\apache\derby\loc\messages_ja_JP.properties
          M java\engine\org\apache\derby\loc\messages_ko_KR.properties
          M java\engine\org\apache\derby\loc\messages_pt_BR.properties
          M java\engine\org\apache\derby\loc\messages_es.properties
          M java\engine\org\apache\derby\loc\messages_fr.properties
          M java\engine\org\apache\derby\loc\messages_zh_TW.properties
          M java\engine\org\apache\derby\loc\messages_it.properties
          A java\common
          A java\common\org
          A java\common\org\apache
          A java\common\org\apache\derby
          A java\common\org\apache\derby\common
          A java\common\org\apache\derby\common\i18n
          A java\common\org\apache\derby\common\i18n\MessageUtil.java
          A java\common\org\apache\derby\common\CommonInfo.java
          A java\common\org\apache\derby\common\SharedComponentInfo.java
          A java\common\org\apache\derby\common\sanity
          A java\common\org\apache\derby\common\sanity\SanityManager.java
          A java\common\org\apache\derby\common\sanity\SanityState.tmpl
          A java\common\org\apache\derby\common\sanity\SanityState.java
          A java\common\org\apache\derby\common\sanity\AssertFailure.java
          A java\common\org\apache\derby\common\CommonFeatures.java
          A java\common\org\apache\derby\common\error
          A java\common\org\apache\derby\common\error\ExceptionSeverity.java
          A java\common\org\apache\derby\common\error\ExceptionUtil.java
          A java\common\org\apache\derby\common\package.html
          A java\common\org\apache\derby\loc
          A java\common\org\apache\derby\loc\common-messages_es.properties
          A java\common\org\apache\derby\loc\common-messages_fr.properties
          A java\common\org\apache\derby\loc\common-messages_zh_TW.properties
          A java\common\org\apache\derby\loc\common-messages_it.properties
          A java\common\org\apache\derby\loc\common-messages.properties
          A java\common\org\apache\derby\loc\common-messages_de_DE.properties
          A java\common\org\apache\derby\loc\common-messages_zh_CN.properties
          A java\common\org\apache\derby\loc\common-messages_en.properties
          A java\common\org\apache\derby\loc\common-messages_ja_JP.properties
          A java\common\org\apache\derby\loc\common-messages_ko_KR.properties
          A java\common\org\apache\derby\loc\common-messages_pt_BR.properties
          A java\common\org\apache\derby\loc\build.xml
          A java\common\build.xml
          M java\testing\org\apache\derbyTesting\functionTests\tests\tools\build.xml
          A java\testing\org\apache\derbyTesting\functionTests\tests\common
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\FeatureManagement_app.properties
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc1
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc1\TestSCInfo.java
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc1\TestSCFeatures.java
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc1\TestSharedClass.java
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2\NewClass.java
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2\TestSCInfo.java
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2\TestSCFeatures.java
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2\newPackage
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2\newPackage\NewPackageClass.java
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2\TestSharedClass.java
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\FeatureManagement.java
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\build.xml
          A java\testing\org\apache\derbyTesting\functionTests\tests\common\copyfiles.ant
          M java\testing\org\apache\derbyTesting\functionTests\tests\jdbcapi\build.xml
          A java\testing\org\apache\derbyTesting\functionTests\master\FeatureManagement.out
          M java\testing\build.xml
          M java\client\org\apache\derby\jdbc\ClientBaseDataSource.java
          A java\client\org\apache\derby\loc
          A java\client\org\apache\derby\loc\client-messages_en.properties
          A java\client\org\apache\derby\loc\build.xml
          A java\client\org\apache\derby\loc\client-messages.properties
          A java\client\org\apache\derby\client\i18n
          A java\client\org\apache\derby\client\i18n\ClientMessageUtil.java
          M java\client\org\apache\derby\client\ClientPooledConnection.java
          M java\client\org\apache\derby\client\am\Connection.java
          A java\client\org\apache\derby\client\am\SqlException2.java
          M java\client\org\apache\derby\client\am\SqlException.java
          M java\client\build.xml
          M build.xml

          Show
          David Van Couvering added a comment - Hi, all. Here is the proposed patch that provides the framework for code sharing. I was thinking folks could look at it and discuss, and then once issues have (hopefully) been worked out, we can have a vote. When you apply these changes, you need to manually create an empty master file master/FeatureManagement.out Summary of changes: Created new top-level source directory trunk/java/common common/org/apache/derby/common/package.html has a full description of the framework and the guidelines around it. This is an updated version of the policy as we worked out on the Wiki. The intention is that this becomes the official guidelines (and gets updated as needed) once we vote on this and it gets checked in Created some utilities for i18n and error handling that both the engine and network client make use of Created a new SQLException class for the client, SQLException2, which makes use of the common framework. I did this rather than modify the existing class because I wanted a well-structured way to migrate exception code over incrementally. Relocated iapi.services.sanity from the engine to the common area, since it's shared by all (there are more opportunities like this, but this seemed like the simplest example) Moved a few messages from the engine's messages_en.properties under the engine directory to common-messages_en.properties under the common directory. Note that I did not at this time move all the translations over. This is a tedious manual job and I am going to write a tool to do this automatically once all the messages are relocated (or we are ready for a release, whichever comes first). Note that I did NOT move SQLState from iapi.reference at this time. What do you all think – should this be relocated at some point, since it is shared code? It's irrelevant at runtime since it's a class that is simply constants, so it doesn't even get included at runtime. Also Created some unit tests for the feature management aspects of the common framework under tests/common. These are written as JUnit tests. They can be relocated at some point if we identify a single area for new JUnit tests Modified the build to build the common code. I noticed that the build infrastructure automatically picked up common code that the various jar files depended on for derby.jar, derbytools.jar and derbynet.jar. This did not appear to be the case for the client jar, so I modified the derbyclientjar build target to add the common classes This passes derbyall. The new unit tests for the common framework are not included in derbyall as they can only be run against the classes directory, not against jar files. This is because the unit tests depend on two "shared component" jar files, and my classloader can't seem to find the classes inside them when they are embedded inside another jar file (e.g. derbyTesting.jar). They need to be jar files because they are two different versions of the same component and they need to be sealed. An alternative approach is to keep them outside of derbyTesting but I was loathe to add the requirement for two more jar files in the classpath to run derbyall. svn status output: M tools\ant\properties\dirs.properties M java\tools\org\apache\derby\impl\tools\sysinfo\Main.java M java\engine\org\apache\derby\impl\services\monitor\BaseMonitor.java M java\engine\org\apache\derby\iapi\services\i18n\BundleFinder.java M java\engine\org\apache\derby\iapi\services\i18n\MessageService.java M java\engine\org\apache\derby\iapi\services\sanity\SanityManager.java D java\engine\org\apache\derby\iapi\services\sanity\SanityState.tmpl M java\engine\org\apache\derby\iapi\services\sanity\AssertFailure.java M java\engine\org\apache\derby\iapi\error\StandardException.java M java\engine\org\apache\derby\iapi\error\ExceptionSeverity.java M java\engine\org\apache\derby\iapi\reference\SQLState.java M java\engine\org\apache\derby\loc\messages_de_DE.properties M java\engine\org\apache\derby\loc\messages_zh_CN.properties M java\engine\org\apache\derby\loc\messages_en.properties M java\engine\org\apache\derby\loc\messages_ja_JP.properties M java\engine\org\apache\derby\loc\messages_ko_KR.properties M java\engine\org\apache\derby\loc\messages_pt_BR.properties M java\engine\org\apache\derby\loc\messages_es.properties M java\engine\org\apache\derby\loc\messages_fr.properties M java\engine\org\apache\derby\loc\messages_zh_TW.properties M java\engine\org\apache\derby\loc\messages_it.properties A java\common A java\common\org A java\common\org\apache A java\common\org\apache\derby A java\common\org\apache\derby\common A java\common\org\apache\derby\common\i18n A java\common\org\apache\derby\common\i18n\MessageUtil.java A java\common\org\apache\derby\common\CommonInfo.java A java\common\org\apache\derby\common\SharedComponentInfo.java A java\common\org\apache\derby\common\sanity A java\common\org\apache\derby\common\sanity\SanityManager.java A java\common\org\apache\derby\common\sanity\SanityState.tmpl A java\common\org\apache\derby\common\sanity\SanityState.java A java\common\org\apache\derby\common\sanity\AssertFailure.java A java\common\org\apache\derby\common\CommonFeatures.java A java\common\org\apache\derby\common\error A java\common\org\apache\derby\common\error\ExceptionSeverity.java A java\common\org\apache\derby\common\error\ExceptionUtil.java A java\common\org\apache\derby\common\package.html A java\common\org\apache\derby\loc A java\common\org\apache\derby\loc\common-messages_es.properties A java\common\org\apache\derby\loc\common-messages_fr.properties A java\common\org\apache\derby\loc\common-messages_zh_TW.properties A java\common\org\apache\derby\loc\common-messages_it.properties A java\common\org\apache\derby\loc\common-messages.properties A java\common\org\apache\derby\loc\common-messages_de_DE.properties A java\common\org\apache\derby\loc\common-messages_zh_CN.properties A java\common\org\apache\derby\loc\common-messages_en.properties A java\common\org\apache\derby\loc\common-messages_ja_JP.properties A java\common\org\apache\derby\loc\common-messages_ko_KR.properties A java\common\org\apache\derby\loc\common-messages_pt_BR.properties A java\common\org\apache\derby\loc\build.xml A java\common\build.xml M java\testing\org\apache\derbyTesting\functionTests\tests\tools\build.xml A java\testing\org\apache\derbyTesting\functionTests\tests\common A java\testing\org\apache\derbyTesting\functionTests\tests\common\FeatureManagement_app.properties A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc1 A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc1\TestSCInfo.java A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc1\TestSCFeatures.java A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc1\TestSharedClass.java A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2 A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2\NewClass.java A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2\TestSCInfo.java A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2\TestSCFeatures.java A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2\newPackage A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2\newPackage\NewPackageClass.java A java\testing\org\apache\derbyTesting\functionTests\tests\common\sc2\TestSharedClass.java A java\testing\org\apache\derbyTesting\functionTests\tests\common\FeatureManagement.java A java\testing\org\apache\derbyTesting\functionTests\tests\common\build.xml A java\testing\org\apache\derbyTesting\functionTests\tests\common\copyfiles.ant M java\testing\org\apache\derbyTesting\functionTests\tests\jdbcapi\build.xml A java\testing\org\apache\derbyTesting\functionTests\master\FeatureManagement.out M java\testing\build.xml M java\client\org\apache\derby\jdbc\ClientBaseDataSource.java A java\client\org\apache\derby\loc A java\client\org\apache\derby\loc\client-messages_en.properties A java\client\org\apache\derby\loc\build.xml A java\client\org\apache\derby\loc\client-messages.properties A java\client\org\apache\derby\client\i18n A java\client\org\apache\derby\client\i18n\ClientMessageUtil.java M java\client\org\apache\derby\client\ClientPooledConnection.java M java\client\org\apache\derby\client\am\Connection.java A java\client\org\apache\derby\client\am\SqlException2.java M java\client\org\apache\derby\client\am\SqlException.java M java\client\build.xml M build.xml
          Hide
          Rick Hillegas added a comment -

          o Yes, please. Please move SQLState.java to common.

          o CommonFeatures doesn't seem to provide much value. Could it be merged into SharedComponentInfo?

          o I'm curious about the catching of ShutdownException in MessageServices after calling MessageUtil.getCompleteMessage(). Do you understand how this exception is raised?

          o You might want to hold off on this submission until you check in my compatibility test patch which moves the JUnit tests under their own subdirectory in the code tree. That will avoid the nasty svn-moving of your tests.

          Show
          Rick Hillegas added a comment - o Yes, please. Please move SQLState.java to common. o CommonFeatures doesn't seem to provide much value. Could it be merged into SharedComponentInfo? o I'm curious about the catching of ShutdownException in MessageServices after calling MessageUtil.getCompleteMessage(). Do you understand how this exception is raised? o You might want to hold off on this submission until you check in my compatibility test patch which moves the JUnit tests under their own subdirectory in the code tree. That will avoid the nasty svn-moving of your tests.
          Hide
          Kathey Marsden added a comment -

          Dan had mentioned in a thread on a different topic:
          "In addition most of the packages in derby.jar are now sealed, which
          means that classes in a sealed package must be loaded from the same jar."

          I think this might be a problem for the code sharing proposal which relies on the ability of one jar to be able to load the class from the other jar if the other jar is loaded first. It seems we would get an error if the package was sealed.

          Show
          Kathey Marsden added a comment - Dan had mentioned in a thread on a different topic: "In addition most of the packages in derby.jar are now sealed, which means that classes in a sealed package must be loaded from the same jar." I think this might be a problem for the code sharing proposal which relies on the ability of one jar to be able to load the class from the other jar if the other jar is loaded first. It seems we would get an error if the package was sealed.
          Hide
          David Van Couvering added a comment -

          I am aware of the package sealing issue. The unit test I wrote actually has a test case that shows what package sealing does. One way package sealing impacts things that new classes can not be loaded from a package where a class was already loaded from the old jar file – it's another form of "shadowing".

          David

          Show
          David Van Couvering added a comment - I am aware of the package sealing issue. The unit test I wrote actually has a test case that shows what package sealing does. One way package sealing impacts things that new classes can not be loaded from a package where a class was already loaded from the old jar file – it's another form of "shadowing". David
          Hide
          David Van Couvering added a comment -

          Now that the i18n work is pretty much done and the 10.1.3 release is
          closed, I'd like to revisit our beloved issue of code sharing.

          I have had time to think about this further, and believe it or not I
          am warming to Kathey's proposed approach. I'd like to propose a
          refinement to this here, and get your feedback.

          I'd like to desribe the proposal in terms of an example. Let's say
          we have a class we want to share between derbyclient jar and
          derby.jar, called DavidUtil. Here's how I would share it.

          (a) Create the class under the shared package hierarchy (or move
          it if it is an existing class. Yes, yes, I know it needs
          copyrights and javadoc

          package org.apache.derby.shared.common;

          public class DavidUtil {
          public int foo(int a, int b)

          { // code here }

          }

          (b) Add an ant target that takes all classes under
          org.apache.derby.shared and makes a copy of them under
          org.apache.derby.shared.generated.client. This would need
          to be done prior to any compilation.

          Yes, I know the package name is a mouthful, but we really should
          have the "generated" package name to make it clear this is generated
          code. The alternative is to add a comment, but then the line numbers
          are out of sync between generated and original code, and this makes
          debugging very difficult.

          If we also want to create shared classes for derbynet and
          derbytools, we would create copies there too. For example:

          package org.apache.derby.shared.generated.client.common;

          public class DavidUtil {
          public int foo(int a, int b)

          { // code here }
          }

          ==
          package org.apache.derby.shared.generated.net.common;

          public class DavidUtil {
          public int foo(int a, int b) { // code here }

          }
          ==
          package org.apache.derby.shared.generated.tools.common;

          public class DavidUtil {
          public int foo(int a, int b)

          { // code here }

          }

          Although this needs to be tested and verified, The 'generated' directory
          would be marked as a directory to be ignored by subversion using the
          svn:ignore property. This way these files would not show up under
          svn status as "?" and could not be checked in by accident.

          (c) In the engine code (e.g. the classes that go into derby.jar),
          I import org.apache.derby.shared.common.DavidUtil.

          In the client code I import
          org.apache.derby.shared.generated.client.common.DavidUtil

          and so on...

          (d) During runtime, the stack trace on the client will show
          the generated class. The line numbers should match because
          we're not adding or removing any lines, just modifying the
          package name.

          ADVANTAGES

          • Meets all the requirements of shared code. Each jar has a distinct
            and separate class. There is no potential for shadowing and
            compatibility issues in mixed-version environments.
          • Simple to implement and fairly simple understand (my concern about
            the classloader solution has been its overall complexity and that it
            would require most developers to understand the subtleties of
            classloading to be able to work with parts of Derby).

          DISADVANTAGES

          • Potential of confusion for developers who try to modify
            generated code or add new classes to the generated packages.
            This is mitigated by the "generated" part of the package name
            and the fact that the generated directories are ignored by
            subversion.
          • Doesn't solve the more general problem of being able to include
            third-party jar files and share them between derby jar files
            in a mixed-version environment. I would argue this
            is a different problem to solve and less urgent than sharing code
            within Derby itself.

          Your thoughts are most appreciated.

          Thanks,

          David

          Show
          David Van Couvering added a comment - Now that the i18n work is pretty much done and the 10.1.3 release is closed, I'd like to revisit our beloved issue of code sharing. I have had time to think about this further, and believe it or not I am warming to Kathey's proposed approach. I'd like to propose a refinement to this here, and get your feedback. I'd like to desribe the proposal in terms of an example. Let's say we have a class we want to share between derbyclient jar and derby.jar, called DavidUtil. Here's how I would share it. (a) Create the class under the shared package hierarchy (or move it if it is an existing class. Yes, yes, I know it needs copyrights and javadoc package org.apache.derby.shared.common; public class DavidUtil { public int foo(int a, int b) { // code here } } (b) Add an ant target that takes all classes under org.apache.derby.shared and makes a copy of them under org.apache.derby.shared.generated.client. This would need to be done prior to any compilation. Yes, I know the package name is a mouthful, but we really should have the "generated" package name to make it clear this is generated code. The alternative is to add a comment, but then the line numbers are out of sync between generated and original code, and this makes debugging very difficult. If we also want to create shared classes for derbynet and derbytools, we would create copies there too. For example: package org.apache.derby.shared.generated.client.common; public class DavidUtil { public int foo(int a, int b) { // code here } } == package org.apache.derby.shared.generated.net.common; public class DavidUtil { public int foo(int a, int b) { // code here } } == package org.apache.derby.shared.generated.tools.common; public class DavidUtil { public int foo(int a, int b) { // code here } } Although this needs to be tested and verified, The 'generated' directory would be marked as a directory to be ignored by subversion using the svn:ignore property. This way these files would not show up under svn status as "?" and could not be checked in by accident. (c) In the engine code (e.g. the classes that go into derby.jar), I import org.apache.derby.shared.common.DavidUtil. In the client code I import org.apache.derby.shared.generated.client.common.DavidUtil and so on... (d) During runtime, the stack trace on the client will show the generated class. The line numbers should match because we're not adding or removing any lines, just modifying the package name. ADVANTAGES Meets all the requirements of shared code. Each jar has a distinct and separate class. There is no potential for shadowing and compatibility issues in mixed-version environments. Simple to implement and fairly simple understand (my concern about the classloader solution has been its overall complexity and that it would require most developers to understand the subtleties of classloading to be able to work with parts of Derby). DISADVANTAGES Potential of confusion for developers who try to modify generated code or add new classes to the generated packages. This is mitigated by the "generated" part of the package name and the fact that the generated directories are ignored by subversion. Doesn't solve the more general problem of being able to include third-party jar files and share them between derby jar files in a mixed-version environment. I would argue this is a different problem to solve and less urgent than sharing code within Derby itself. Your thoughts are most appreciated. Thanks, David
          Hide
          Rick Hillegas added a comment -

          A small refinement:

          I'd like to see the generated files go under a subdirectory parallel to classes and java. The generated subtree can be wholesale whacked when you clobber your workspace.

          Show
          Rick Hillegas added a comment - A small refinement: I'd like to see the generated files go under a subdirectory parallel to classes and java. The generated subtree can be wholesale whacked when you clobber your workspace.
          Hide
          David Van Couvering added a comment -

          Unassigning this for now, I am not able to work on this right now.

          Show
          David Van Couvering added a comment - Unassigning this for now, I am not able to work on this right now.
          Hide
          Rick Hillegas added a comment -

          Moving to 10.2.2.0.

          Show
          Rick Hillegas added a comment - Moving to 10.2.2.0.
          Hide
          Rick Hillegas added a comment -

          Move to 10.2.3.0.

          Show
          Rick Hillegas added a comment - Move to 10.2.3.0.
          Hide
          Rick Hillegas added a comment -

          Er, make that 10.3.0.0.

          Show
          Rick Hillegas added a comment - Er, make that 10.3.0.0.
          Hide
          Andrew McIntyre added a comment -

          Unsetting Fix Version on unassigned issues.

          Show
          Andrew McIntyre added a comment - Unsetting Fix Version on unassigned issues.

            People

            • Assignee:
              Unassigned
              Reporter:
              David Van Couvering
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:

                Development