-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 21 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: How to add pre/post conditions to generated set/get methods
PostPosted: Fri Sep 08, 2006 4:52 am 
Beginner
Beginner

Joined: Mon Nov 28, 2005 11:03 am
Posts: 39
Location: Madrid
Dear member,

I would like to know how to add for a particular property a post condition or pre condition for a generat set method. For example I would like to generate an IllegalArgumentException in case the input argument of the set is negative. The generated code doesn't controll such situation.

I was trying to use:

Code:
<property name="settledPosition" type="java.lang.Integer">
  <meta attribute="use-in-tostring">true</meta>
    <meta attribute="class-code">
       final Integer zero = new Integer(0);
       if (zero.compareTo(settledPosition) > 0) {
         throw new IllegalArgumentException(settledPosition.toString());
       }               
     </meta>
   <column name="settled_position" />
</property>


I would like to get the generated set method:

Code:
public void setSettledPosition(Integer settledPosition) {
       final Integer zero = new Integer(0);
       if (zero.compareTo(settledPosition) > 0) {
         throw new IllegalArgumentException(settledPosition.toString());
       }               
        this.settledPosition = settledPosition;
    }


but it doesn't work, such addional piece of code is not generated.

for the property settledPosition, but this meta attribute works only for adding methods to the class and not for adding peace of code for a methods generated.

Do you have to use a new template for such particular class?, can some one could give some hint about how to do it in this case.

Thanks,

David

P.S.: I can't use now inheritance for overriding this set method, because I have to propagate this change on all my classes (the application is big), I am thinking about using AOP for adding this behaviour, but I hope it could be solve easiers using hibernate tools generation.

_________________
David Leal


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 09, 2006 10:31 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
change the templates to make them generate different code.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 09, 2006 10:37 am 
Beginner
Beginner

Joined: Mon Nov 28, 2005 11:03 am
Posts: 39
Location: Madrid
max wrote:
change the templates to make them generate different code.


Max, I just want to change the behaviour for a particular property, no for all my generated get/set methods.

Changing the template will affect all properties.

Please, let me know any suggestion,

Thanks,

David

_________________
David Leal


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 09, 2006 11:28 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
use an if statement that checks for a meta property or column name to do alternative generation.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject: I have added an improvement into Jira for this problem...
PostPosted: Sun Sep 10, 2006 9:29 am 
Beginner
Beginner

Joined: Mon Nov 28, 2005 11:03 am
Posts: 39
Location: Madrid
max wrote:
use an if statement that checks for a meta property or column name to do alternative generation.


Max, thanks again for your suggestion. I think for the moment as you said, there no other way to solve this problem, than modifying the template, that is way I have added an improvement on JIRA, in order to have in a future a better solution for this problem.

http://opensource.atlassian.com/projects/hibernate/browse/HBX-752

Thanks,

David Leal

_________________
David Leal


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 11, 2006 5:46 pm 
Beginner
Beginner

Joined: Mon Nov 28, 2005 11:03 am
Posts: 39
Location: Madrid
Following the max comments about my issue on JIRA, the only solution will be to modify the template.

I guess the template to modify is:

http://anonhibernate.labs.jboss.com/tru ... essors.ftl:

Code:
<#-- if interface -->
<#-- Property accessors for interface -->
<#foreach property in pojo.getAllPropertiesIterator()><#if pojo.getMetaAttribAsBool(property, "gen-property", true)>   /**
   ${c2j.toJavaDoc(c2j.getMetaAsString(property, "field-description"), 4)} */
   ${pojo.getPropertyGetModifiers(property)} ${pojo.getJavaTypeName(property, jdk5)} ${pojo.getGetterSignature(property)}();
   
   ${pojo.getPropertySetModifiers(property)} void set${pojo.getPropertyName(property)}(${pojo.getJavaTypeName(property, jdk5)} ${property.name});
</#if></#foreach>


but on the set definition, I don't see were is defined the body of the set operation.

Clease could you give me som hint about how to modify the corresponding template.

I would like to add a precondition, before a code assignation, for a particular property, for example: position.

Thanks in advance,

David

_________________
David Leal


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 11, 2006 5:50 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
that one is for the interface, hence the interface part.

See http://anonhibernate.labs.jboss.com/tru ... essors.ftl for actuall propertyaccessors.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject: How to specify that a property belong to a particular class?
PostPosted: Wed Sep 13, 2006 6:30 am 
Beginner
Beginner

Joined: Mon Nov 28, 2005 11:03 am
Posts: 39
Location: Madrid
max wrote:
that one is for the interface, hence the interface part.

See http://anonhibernate.labs.jboss.com/tru ... essors.ftl for actuall propertyaccessors.


Looking int to this template, so the new template will be:

<#foreach property in pojo.getAllPropertiesIterator()>
<#if pojo.getMetaAttribAsBool(property, "gen-property", true)>
<#if pojo.hasFieldJavaDoc(property)>
/**
* ${pojo.getFieldJavaDoc(property, 4)}
*/
</#if>
<#include "Ejb3PropertyGetAnnotation.ftl"/>
${pojo.getPropertyGetModifiers(property)} ${pojo.getJavaTypeName(property, jdk5)} ${pojo.getGetterSignature(property)}() {
return this.${property.name};
}

${pojo.getPropertySetModifiers(property)} void set${pojo.getPropertyName(property)}(${pojo.getJavaTypeName(property, jdk5)} ${property.name}) {
<#if ${property.name} = "settledPosition">
throw new IllegalArgumentException(String.valueO(settledPosition));
</#if>

this.${property.name} = ${property.name};
}
</#if>
</#foreach>

but, what about if the property settledPosition, is used on other classes?, so I need to distinguish the situation, so the throw sentence will be generated ONLY for the property settledPosition belong to the class: com.schinvest.lra.domain.Position. Do you have any suggestion about how to control this situation.

I think that in order to use this new template, without modifying the original file on the jar, I have to put this template first on the classpath, isn't it?

Thanks in advance,

David Leal

_________________
David Leal


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 13, 2006 6:49 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
probably better if you add a meta attribute to the properties you want specific behavior for and then check for that in the templates.

regarding templates you just need to set the templatepath to the root of your custom templates (putting them in front of the classpath might also work, but templatepath is the right way)

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 13, 2006 6:17 pm 
Beginner
Beginner

Joined: Mon Nov 28, 2005 11:03 am
Posts: 39
Location: Madrid
max wrote:
probably better if you add a meta attribute to the properties you want specific behavior for and then check for that in the templates.


Max, following your recomendation, I am on the way, to the condition has to be improved. I have the following:

Code:
  ${pojo.getPropertySetModifiers(property)} void set${pojo.getPropertyName(property)}(${pojo.getJavaTypeName(property, jdk5)} ${property.name}) {
<#if pojo.getMetaAttribAsBool(property, "settledPosition", true)>
   System.out.println("hola");
</#if>
        this.${property.name} = ${property.name};
    }


so, I want to check that settledPosition is present and true, then on the hbm file I have:

Code:
<property name="settledPosition" type="java.lang.Integer">
            <meta attribute="settledPosition">true</meta>
            <column name="settled_position" />
  </property>


but I get System.out.println("hola"), on all my set methods for all generated classes.

Please could you give me any hint about this?,

Thanks again,

David

_________________
David Leal


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 14, 2006 1:57 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
well that is because you are putting "true" in the last argument which is the default value if none is found ;)

Also note that another cause can be that you have put the meta element in the top of the file and all properties have inherited it - you avoid that with inherit="false"

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 16, 2006 1:24 pm 
Beginner
Beginner

Joined: Mon Nov 28, 2005 11:03 am
Posts: 39
Location: Madrid
max wrote:
well that is because you are putting "true" in the last argument which is the default value if none is found ;)

Also note that another cause can be that you have put the meta element in the top of the file and all properties have inherited it - you avoid that with inherit="false"


On the original file you will see a similar use of getMetaAttribAsBool, at that place it uses the third argument too:

Code:
<#if pojo.getMetaAttribAsBool(property, "gen-property", true)>
<#if pojo.hasFieldJavaDoc(property)>   
    /**       
     * ${pojo.getFieldJavaDoc(property, 4)}
     */
</#if>


What I am duing is the same, if I don't put the true I get an Exception.

Conserning to the second suggestion, I am putting on the meta attribute on the property definition, not at the begining of the file, I have tried this posibility also, but I get the same result.

Your suggestion look good and with sense, but it doesn't work, probably because if you put a new meta attribute you have to tell hibernate it is a new meta attribute. As you can see I am using the same sintax as for property "gen-property", but hibernate expect such meta attribute.

It is a common problem (adding pre/post conditions), but it doesn't look so simple to really get the desire output. Have you tried such suggestion about meta attribute really? Where I can find the definition of the method invoked on the *.ftl files. I know it is Freemarker, but there are defined some method specifically for hibernate. For example like the method:

Code:
<#if pojo.hasMetaAttribute("class-code")>  // The following is extra code specified in the hbm.xml files
${pojo.getExtraClassCode()}
  // end of extra code specified in the hbm.xml files
</#if>


where is such getExtraClassCode defined?

On my opinions, it should be easier to define a method like getPreConditionMethodCode(), getPostConditionMethodCode(), that to get finally work modifying the template, :-)

Any why there is no so much documetation about how to add additional conditions to the generated methods, I would like it works but it doesn't.

Please let me know any other suggestion, and thanks again.

David

_________________
David Leal


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 17, 2006 4:23 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
dleal wrote:
max wrote:
well that is because you are putting "true" in the last argument which is the default value if none is found ;)

Also note that another cause can be that you have put the meta element in the top of the file and all properties have inherited it - you avoid that with inherit="false"


On the original file you will see a similar use of getMetaAttribAsBool, at that place it uses the third argument too:

Code:
<#if pojo.getMetaAttribAsBool(property, "gen-property", true)>
<#if pojo.hasFieldJavaDoc(property)>   
    /**       
     * ${pojo.getFieldJavaDoc(property, 4)}
     */
</#if>


What I am duing is the same, if I don't put the true I get an Exception.


yes, because then it will return null and thus be undefined.
if not all elements has the meta attribute and no reasonable default is possible (you could maybe use an empty string?) then you should use the c2j.hasMetaAttribute(property, "blahblah") method (the ones on pojo is just shortcuts to this one.)

Then you can check if the property has the value or not.

Quote:
Your suggestion look good and with sense, but it doesn't work, probably because if you put a new meta attribute you have to tell hibernate it is a new meta attribute. As you can see I am using the same sintax as for property "gen-property", but hibernate expect such meta attribute.


yes - its still simple and it works just as described.

Quote:
It is a common problem (adding pre/post conditions), but it doesn't look so simple to really get the desire output. Have you tried such suggestion about meta attribute really?


The templates are full of dependencies on metaattribute working so yes i have tried it.

Quote:
Where I can find the definition of the method invoked on the *.ftl files. I know it is Freemarker, but there are defined some method specifically for hibernate. For example like the method:

Code:
<#if pojo.hasMetaAttribute("class-code")>  // The following is extra code specified in the hbm.xml files
${pojo.getExtraClassCode()}
  // end of extra code specified in the hbm.xml files
</#if>


where is such getExtraClassCode defined?


On POJOClass.

Quote:
On my opinions, it should be easier to define a method like getPreConditionMethodCode(), getPostConditionMethodCode(), that to get finally work modifying the template, :-)


see http://www.hibernate.org/hib_docs/tools ... e/#d0e1179 for how to expose your own java logic.

Quote:
Any why there is no so much documetation about how to add additional conditions to the generated methods, I would like it works but it doesn't.


no one haven't sat down and written it yet. Want to contribute it ?

Your case would actually be a good way to demonstrate how to extend the templates.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject: EUREKA: Finally it works
PostPosted: Sun Sep 17, 2006 9:29 am 
Beginner
Beginner

Joined: Mon Nov 28, 2005 11:03 am
Posts: 39
Location: Madrid
Max and members,

Yust to send a final post to explain in detail how it works with the help of Max hints.

1. Copy the template PojoPropertyAccessors.ftl from hibernatetools.jar into a local directory. NOTE: In order hibernatetools can find it, you have to respect the same directory structure, for example:

Code:
${project.dir}/src/orm/hibernate/template/pojo/PojoPropertyAccessors.ftl


Now add the location:

Code:
${project.dir}/src/orm/hibernate/template


to the templatepath definition on hbm2java:

Code:

<target name="hbm2java" unless="hbm2java.skip"
  description="Generates default java files from *.hbml.xml files">
  <taskdef name="hibernatetool"
      classname="org.hibernate.tool.ant.HibernateToolTask"
      classpathref="lib.classpath"/>
  <hibernatetool
     destdir="${hbm2java.dest.dir}
     templatepath="${src.orm.hbm.dir}/template"
     >
     <classpath>
         <path refid="lib.classpath"/>
     </classpath>
    <configuration>
       <fileset dir="${hbm2java.src.dir}">
          <include name="**/*.hbm.xml"/>
          <exclude name="**/queries*.hbm.xml"/>
       </fileset>
    </configuration>
    <hbm2java/>
  </hibernatetool>
</target>


where lib.classpath includes the hibernatetools.jar and ${src.orm.hbm.dir} points to:

Code:
${project.dir}/src/orm/hibernate


2. Define a meta-attribute pre-settled_position on the mapping file: Position.hbm.xml.

Code:
<property name="settledPosition" type="java.lang.Integer">           
  <meta attribute="pre-settled_position"/>
  <column name="settled_position" />
</property>


Note: You can add the meta-attribute settting it to true, for example:
<meta attribute="pre-settled_position">true</meta>

3. Finally on the template PojoPropertyAccessors.ftl, modify the generation of set method so if meta attribute pre-settled_position is pressent a pre-condition will be added:

Code:
${pojo.getPropertySetModifiers(property)} void set${pojo.getPropertyName(property)}(${pojo.getJavaTypeName(property, jdk5)} ${property.name}) {
    <#if pojo.hasMetaAttribute(property, "pre-settled_position")>
        if ((${property.name} != null) && (${property.name}.intValue() < 0)) {
          throw new IllegalArgumentException(${property.name}.toString());
        }
    </#if>
        this.${property.name} = ${property.name};
    }


4. Now after invoking: hbm2java target I get the following setSettledPosition method:

Code:
  public void setSettledPosition(Integer settledPosition) {
        if ((settledPosition != null) && (settledPosition.intValue() < 0)) {
           throw new IllegalArgumentException(settledPosition.toString());
        }
        this.settledPosition = settledPosition;
    }


that's all folks,

Replying to Max:

1. Max let me know how to colaborate (on my Jira profile you can find me e-mail) on improving the documentation. I have only one problem: I am not english native, so probably I will need some help for correcting my english mistakes.

2. I think like you it is a good example for defining new templates, nevertheless if you open the door for adding extra code, it is a natural extension to meta attribute the class-code, to add a similar attributes for pre/post condition on methods. I am going to explain in more detail my reasons on the JIRA issue:

http://opensource.atlassian.com/projects/hibernate/browse/HBX-752

I think it is the right place for comment that,


Thanks,

David

_________________
David Leal


Top
 Profile  
 
 Post subject: Re: EUREKA: Finally it works
PostPosted: Sun Sep 17, 2006 5:07 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
dleal wrote:
...snip example...


your example is good, i would just put the code into the hbm.xml instead of just having true/false in the property.

Quote:
[i]1. Max let me know how to colaborate (on my Jira profile you can find me e-mail) on improving the documentation. I have only one problem: I am not english native, so probably I will need some help for correcting my english mistakes.


i'm also not english native so don't worry ;)

improving documentation is best done by submitting a patch to the docs in the doc directory. It's just docbook so is pretty straightforward.

Quote:
2. I think like you it is a good example for defining new templates, nevertheless if you open the door for adding extra code, it is a natural extension to meta attribute the class-code, to add a similar attributes for pre/post condition on methods. I am going to explain in more detail my reasons on the JIRA issue:


there is a big difference between static extra code and context sensitive code.

_________________
Max
Don't forget to rate


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 21 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.