nullable VO parameter in service and 1 multiply in VO attribute cause NullpointerException in ServiceBase

Description

Here's a shema:

VO:
attribute1: Long
attribute2: String [0..1]

Service:
i. void service(VO vo);
ii. void service(VO vo[nullable]);

The ServiceBase attribute checker look like this:

i. works fine with null parameter
...
if(vo==null)
throw ...
if(vo.getAttribute1()==null)
throw ...
...

ii. NullpointerException with null paramter
...
!!! missing null check causing the problem!!!
if(vo.getAttribute1()==null)
throw ...
...

The bug is in the SpringServiceBase.vsl

Here's the correct one:

#set ($generatedFile = "${service.packagePath}/${service.baseName}.java")
// license-header java merge-point
//
// Attention: Generated code! Do not modify by hand!
// Generated by: SpringServiceBase.vsl in andromda-spring-cartridge.
//
#if ($stringUtils.isNotBlank($service.packageName))
package $service.packageName;
#end

/**

  • <p>

  • Spring Service base class for <code>$service.fullyQualifiedName</code>,

  • provides access to all services and entities referenced by this service.

  • </p>
    *

  • @see $service.fullyQualifiedName
    */
    public abstract class $service.baseName
    #if($service.generalization)
    extends $service.generalization.fullyQualifiedImplementationName
    #end
    implements $service.fullyQualifiedName
    {

#foreach($serviceRef in $service.serviceReferences)
#set ($targetElement = $serviceRef.targetElement)
private $targetElement.fullyQualifiedName $serviceRef.name;

/**

  • Sets the reference to <code>$serviceRef.name</code>.
    */
    public void ${serviceRef.setterName}(${targetElement.fullyQualifiedName} $serviceRef.name)
    {
    this.$serviceRef.name = $serviceRef.name;
    }

/**

  • Gets the reference to <code>$serviceRef.name</code>.
    */
    protected $targetElement.fullyQualifiedName ${serviceRef.getterName}()
    {
    return this.$serviceRef.name;
    }

#end
#foreach($entityRef in $service.entityReferences)
private $entityRef.targetElement.fullyQualifiedDaoName $entityRef.daoName;

/**

  • Sets the reference to <code>$entityRef.name</code>'s DAO.
    */
    public void ${entityRef.daoSetterName}($entityRef.targetElement.fullyQualifiedDaoName $entityRef.daoName)
    {
    this.$entityRef.daoName = $entityRef.daoName;
    }

/**

  • Gets the reference to <code>$entityRef.name</code>'s DAO.
    */
    protected $entityRef.targetElement.fullyQualifiedDaoName ${entityRef.daoGetterName}()
    {
    return this.$entityRef.daoName;
    }

#end
#foreach ($operation in $service.implementationOperations)
/**

  • @see ${service.fullyQualifiedName}#${operation.getSignature(false)}
    */
    $operation.visibility $operation.returnType.fullyQualifiedName $operation.signature
    #if ($operation.exceptionsPresent)
    $operation.throwsClause
    #end
    {
    #if ($requiredCheckEnabled)
    #foreach ($argument in $operation.arguments)
    #if ($argument.required && !$argument.type.primitive)
    #if (!$argument.type.stringType)
    if ($argument.name == null)
    {
    throw new IllegalArgumentException(
    "${service.fullyQualifiedName}.${operation.signature} - '${argument.name}' can not be null");
    }
    #else
    if ($argument.name == null || ${argument.name}.trim().length() == 0)
    {
    throw new IllegalArgumentException(
    "${service.fullyQualifiedName}.${operation.signature} - '${argument.name}' can not be null or empty");
    }
    #end
    #end
    #if (!$argument.type.enumeration)
    #foreach ($attribute in $argument.type.attributes)
    #if ($attribute.required && !$attribute.type.primitive)
    #if (!$attribute.type.stringType)
    if ($argument.name != null && ${argument.name}.get${stringUtils.capitalize($attribute.name)}() == null)
    {
    throw new IllegalArgumentException(
    "${service.fullyQualifiedName}.${operation.signature} - '$argument.name.$attribute.name' can not be null");
    }
    #else
    if ($argument.name != null && (${argument.name}.get${stringUtils.capitalize($attribute.name)}() == null || ${argument.name}.get${stringUtils.capitalize($attribute.name)}().trim().length() == 0))
    {
    throw new IllegalArgumentException(
    "${service.fullyQualifiedName}.${operation.signature} - '$argument.name.$attribute.name' can not be null or empty");
    }
    #end
    #end
    #end
    #end
    #end
    #end
    #if ($operation.constraintsPresent)
    this.$operation.preconditionCall;
    #end
    try
    {
    #set ($call = "this.${operation.implementationCall};")
    #if ($operation.returnTypePresent)
    return $call
    #else
    $call
    #end
    }
    #foreach($exception in $operation.exceptions)
    catch ($exception.fullyQualifiedName ex)
    {
    throw ex;
    }
    #end
    catch (Throwable th)
    {
    throw new ${service.fullyQualifiedDefaultExceptionName}(
    "Error performing '${service.fullyQualifiedName}.${operation.signature}' --> " + th,
    th);
    }
    }

#if ($operation.constraintsPresent)
/**

  • Performs any precondition checks for {@link #${operation.call}}.
    */
    private void $operation.preconditionSignature
    {
    #renderPreconditions($operation)
    }

#end
/**

  • Performs the core logic for {@link #${operation.getSignature(false)}}
    */
    protected abstract $operation.returnType.fullyQualifiedName $operation.implementationSignature
    throws java.lang.Exception;

#end
/**

  • Gets the current <code>principal</code> if one has been set,

  • otherwise returns <code>null</code>.
    *

  • @return the current principal
    */
    #if ($externalPrincipalStoreClass)
    #set ($principalStoreCall = "#if(!$enableTemplating)(${externalPrincipalStoreGetterType})#end${externalPrincipalStoreClass}.${externalPrincipalStoreGetter};")
    #set ($principalStoreType = ${externalPrincipalStoreGetterType})
    #else
    #set ($principalStoreCall = "${principalStoreName}.get();")
    #if($stringUtils.isNotEmpty($springTypesPackage))
    #set ($principalStoreCall = "${springTypesPackage}.${principalStoreCall}")
    #end
    #set ($principalStoreType = "java.security.Principal")
    #end
    protected $principalStoreType getPrincipal()
    {
    return $principalStoreCall
    }
    #if ($service.webServiceOutgoingAttachmentHandlerCall)

/**

  • Adds an attachment in the webservice's outgoing response message (this only makes sense

  • when the operation this is called within is a web service exposed operation).
    *

  • @param content the actual content to add as the attachment.

  • @param contentType the type of the contents

  • @param dime whether or not DIME should be used (instead of MIME).
    */
    protected void addOutgoingWebServiceAttachment(final Object content, final String contentType, boolean dime)
    throws java.lang.Exception
    {
    $service.webServiceOutgoingAttachmentHandlerCall;
    }
    #end
    #if ($service.webServiceIncomingAttachmentHandlerCall)

/**

  • Retrieves any incoming attachments in the webservice's request message (this only makes sense

  • when the operation this is called within is a web service exposed operation).
    */
    protected javax.xml.soap.AttachmentPart[] getIncomingWebServiceAttachments()
    throws java.lang.Exception
    {
    return $service.webServiceIncomingAttachmentHandlerCall;
    }
    #end
    }

Environment

WinXP SP2, Maven 2, AndroMDA 3.2-SNAPSHOT, MagicDraw 9.5

Assignee

Former user

Reporter

Béla Boda

Labels

None

Components

Priority

Blocker
Configure