umlcode-generationclass-diagramrhapsodyvisual-paradigm

Code Generation from Class Diagram: Composition between two classes does not change anything in generated Java code


I created two simple classes A and B in Visual Paradigm software, such that there there a COMPOSITION between these two classes. However, the generated code (in Java) is the same with OR without the association between these two classes. In other words, the generated code, if there is a composition between class A and B, is the same as when I deleted the composition between class A and class B. That is, the composition between classes is NOT considered in generated code by Visual Paradigm. What is the solution?

Edit: Based on the request of @Christophe, I added the photo of a test example project (class diagram), along with two Java class generated by Visual Paradigm, where in both cases (with and without composition relation between two classes) the generated codes are exactly the same.

enter image description here

Generated codes by Visual Paradigm:

public class Class {

private int attribute;

public void operation() {
    // TODO - implement Class.operation
    throw new UnsupportedOperationException();
}

}

public class Class2 {

private int attribute;

public void operation() {
    // TODO - implement Class2.operation
    throw new UnsupportedOperationException();
}

}

P.S. I tried it with IBM Rational Rhapsody and it works much better. That is, it generates in the code the features of the model in more detail. See the generated code below by IBM Rational Rhapsody and compare the differences with the code generated by Visual Paradigm:

Generated code by IBM Rational Rhapsody:

package Default;


//----------------------------------------------------------------------------
// Default/class_0.java                                                                  
//----------------------------------------------------------------------------

//## package Default 


//## class class_0 
public class class_0 {
    
    protected int attribute_0;      //## attribute attribute_0 
    
    protected class_1 itsClass_1;       //## link itsClass_1 
    
    
    // Constructors
    
    //## auto_generated 
    public  class_0() {
        initRelations();
    }
    
    //## operation Operation_1() 
    public void Operation_1() {
        //#[ operation Operation_1() 
        //#]
    }
    
    //## auto_generated 
    public int getAttribute_0() {
        return attribute_0;
    }
    
    //## auto_generated 
    public void setAttribute_0(int p_attribute_0) {
        attribute_0 = p_attribute_0;
    }
    
    //## auto_generated 
    public class_1 getItsClass_1() {
        return itsClass_1;
    }
    
    //## auto_generated 
    public void __setItsClass_1(class_1 p_class_1) {
        itsClass_1 = p_class_1;
    }
    
    //## auto_generated 
    public void _setItsClass_1(class_1 p_class_1) {
        if(itsClass_1 != null)
            {
                itsClass_1.__setItsClass_0(null);
            }
        __setItsClass_1(p_class_1);
    }
    
    //## auto_generated 
    public class_1 newItsClass_1() {
        itsClass_1 = new class_1();
        itsClass_1._setItsClass_0(this);
        return itsClass_1;
    }
    
    //## auto_generated 
    public void deleteItsClass_1() {
        itsClass_1.__setItsClass_0(null);
        itsClass_1=null;
    }
    
    //## auto_generated 
    protected void initRelations() {
        itsClass_1 = newItsClass_1();
    }
    
}
/*********************************************************************
    File Path   : DefaultComponent/DefaultConfig/Default/class_0.java
*********************************************************************/

Second class code:

package Default;


//----------------------------------------------------------------------------
// Default/class_1.java                                                                  
//----------------------------------------------------------------------------

//## package Default 


//## class class_1 
public class class_1 {
    
    protected int attribute_0;      //## attribute attribute_0 
    
    protected class_0 itsClass_0;       //## link itsClass_0 
    
    
    // Constructors
    
    //## auto_generated 
    public  class_1() {
    }
    
    //## operation Operation_1() 
    public void Operation_1() {
        //#[ operation Operation_1() 
        //#]
    }
    
    //## auto_generated 
    public int getAttribute_0() {
        return attribute_0;
    }
    
    //## auto_generated 
    public void setAttribute_0(int p_attribute_0) {
        attribute_0 = p_attribute_0;
    }
    
    //## auto_generated 
    public class_0 getItsClass_0() {
        return itsClass_0;
    }
    
    //## auto_generated 
    public void __setItsClass_0(class_0 p_class_0) {
        itsClass_0 = p_class_0;
    }
    
    //## auto_generated 
    public void _setItsClass_0(class_0 p_class_0) {
        if(itsClass_0 != null)
            {
                itsClass_0.__setItsClass_1(null);
            }
        __setItsClass_0(p_class_0);
    }
    
    //## auto_generated 
    public void setItsClass_0(class_0 p_class_0) {
        if(p_class_0 != null)
            {
                p_class_0._setItsClass_1(this);
            }
        _setItsClass_0(p_class_0);
    }
    
    //## auto_generated 
    public void _clearItsClass_0() {
        itsClass_0 = null;
    }
    
}
/*********************************************************************
    File Path   : DefaultComponent/DefaultConfig/Default/class_1.java
*********************************************************************/

As you can see, the codes generated by IBM includes the associations (compositions) and other features as well.

Here is the class diagram of above codes generated by IBM Rational Rhapsody:

enter image description here


Solution

  • Does the diagram provide what is needed?

    In your VP diagram you have added a composition relation that leaves a lot of things unspecified:

    Each of these could be an obstacles to the proper code generation:

    Different tools make different assumptions. VP shows the following tool-specific behavior:

    VP generates composition if diagram is sufficient

    Here the diagram I’ll for demo purpose: enter image description here

    The specification of the composition looks like:

    enter image description here

    If there is a role name (here A and B), the code corresponding to the structural relationship is very well generated:

    public class MyClassA {
        private long id;
        Collection<MyClassB> B;  // <========== only if role is in diagram
        public void doSomething() {
            // TODO - implement MyClassA.doSomething
            throw new UnsupportedOperationException();
        }
    }
    
    public class MyClassB {
        private string name;
        MyClassA A;   // <=========================
        public string getName() {
            return this.name;
        }
        public void setName(string name) {
            this.name = name;
        }
    }
    

    By the way, as explained in my earlier answer, the code generated is the same if you'd have an association instead of a composition, because the semantic difference (exclusive inclusion in a composite and deletion of composed elements at the end of the composite lifecycle) is difficult to automate.

    When is the composition not generated?

    If the role names are removed from the specification, the code generated removes the java fields implementing the association; the generated classes then look exactly as if there would be no composition/association at all:

    public class MyClassA {
        private long id;
        public void doSomething() {
            // TODO - implement MyClassA.doSomething
            throw new UnsupportedOperationException();
        }
    }
    public class MyClassB {
        private string name;
        public string getName() {
            return this.name;
        }
        public void setName(string name) {
            this.name = name;
        }
    }
    

    This is the result you have experienced yourself. You could make deliberate use of this behavior, for example getting the association implemented on one side and not on the other (e.g. if B wouldn’t need to know about it’s owning A).

    Missing VP feature? The only thing really missing is a warning message at code generation about the inconsistency between navigability and absence role. Such messages would have saved you a lot of time.

    Remarks: