[ 
https://issues.apache.org/jira/browse/SLING-12104?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Robin Brouns updated SLING-12104:
---------------------------------
    Description: 
Considering the following sample Class:
{code:java}
package com.sample.website.job;

import org.apache.commons.lang3.StringUtils;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;

@Component(service = Runnable.class)
@Designate(ocd = SampleJob.Config.class)
public class SampleJob implements Runnable {    

    private String sampleStringProperty;

    @Activate
    @Modified
    public void update(final Config configuration) {
        this.sampleStringProperty = configuration.sampleStringProperty();
    }    

    @Override
    public void run() {
        if (PathUtils.isAbsolute(this.sampleStringProperty)) {
            // do something
        }
    }    

    @ObjectClassDefinition(
            name = "Sample Configuration",
            description = "Sample Configuration Description"
    )
    @interface Config {        

        @AttributeDefinition(
            name = "Sample String Property",
            description = "Sample String Property"
        )
        String sampleStringProperty() default StringUtils.EMPTY;
    }
} {code}
When I try to test this class with the default OSGi configuration via AEM Mocks:
{code:java}
final Runnable underTest = 
aemContext.registerInjectActivateService(SampleJob.class); {code}
building this class leads to the following SCR definition:
{code:java}
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.3.0"; 
name="com.sample.website.job.SampleJob" activate="update" modified="update">
  <property name="updateImportPath" type="String" value=""/>
  <service>
    <provide interface="java.lang.Runnable"/>
  </service>
  <implementation class="com.sample.website.job.SampleJob"/>
</scr:component>{code}
the *default* value of *updateImportPath* (an empty String) is *not* injected 
in the Configuration, but null is being used, which could lead to NPE.

AEM Mocks uses OSGi Mocks and the following method is used to retrieve the 
*default* properties and values 
[https://github.com/apache/sling-org-apache-sling-testing-osgi-mock/blob/c55d97ba266e0630200fcbb378b3f102d2dfba90/core/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java#L292C24-L292C46]
 

But as you can see the XPath Query doesn't match with the SCR definition: the 
property exists with a *name* and there is a {*}value{*}, but it is empty, so:
{code:java}
String query = getComponentXPathQuery(clazz) + "/property[@name!='' and 
@value!='']"; {code}
doesn't return the property and its default value and the result is a 
Configuration returning *null*

The simple fix would be to check if the *value* attribute exists via the XPath 
Query in the SCR definition, instead of checking for a non empty value.

A more robust fix would probably be to parse the OCD MetaType (if it is a OCD 
config) and use the *default* attribute which is present over there, see:
{code:java}
<?xml version="1.0" encoding="UTF-8"?>
<metatype:MetaData xmlns:metatype="http://www.osgi.org/xmlns/metatype/v1.2.0"; 
localization="OSGI-INF/l10n/com.sample.website.job.SampleJob$Config">
  <OCD id="com.sample.website.job.SampleJob$Config" name="Sample Configuration" 
description="Sample Configuration Description">
    <AD id="updateImportPath" type="String" name="Sample String Property" 
description="Sample String Property" default=""/>
  </OCD>
  <Designate pid="com.sample.website.job.SampleJob">
    <Object ocdref="com.sample.website.job.SampleJob$Config"/>
  </Designate>
</metatype:MetaData>
{code}
What do you think about this?

  was:
Considering the following sample Class:


{code:java}
package com.sample.website.job;

import org.apache.commons.lang3.StringUtils;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;

@Component(service = Runnable.class)
@Designate(ocd = SampleJob.Config.class)
public class SampleJob implements Runnable {    

    private String sampleStringProperty;

    @Activate
    @Modified
    public void update(final Config configuration) {
        this.sampleStringProperty = configuration.sampleStringProperty();
    }    

    @Override
    public void run() {
        if (PathUtils.isAbsolute(this.sampleStringProperty)) {
            // do something
        }
    }    

    @ObjectClassDefinition(
            name = "Sample Configuration",
            description = "Sample Configuration Description"
    )
    @interface Config {        

        @AttributeDefinition(
            name = "Sample String Property",
            description = "Sample String Property"
        )
        String sampleStringProperty() default StringUtils.EMPTY;
    }
} {code}
When I try to test this class with the default OSGi configuration via AEM Mocks:
{code:java}
final Runnable underTest = 
aemContext.registerInjectActivateService(SampleJob.class); {code}
building this class leads to the following SCR definition:
{code:java}
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.3.0"; 
name="com.sample.website.job.SampleJob" activate="update" modified="update">
  <property name="updateImportPath" type="String" value=""/>
  <service>
    <provide interface="java.lang.Runnable"/>
  </service>
  <implementation class="com.sample.website.job.SampleJob"/>
</scr:component>{code}
the *default* value of *updateImportPath* (an empty String) is *not* injected 
in the Configuration, but null is being used, which could lead to NPE.

AEM Mocks uses OSGi Mocks and the following method is used to retrieve the 
*default* properties and values 
[https://github.com/apache/sling-org-apache-sling-testing-osgi-mock/blob/c55d97ba266e0630200fcbb378b3f102d2dfba90/core/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java#L292C24-L292C46]
 

But as you can see the XPath Query doesn't match with the SCR definition: the 
property exists with a *name* and there is a {*}value{*}, but it is empty, so:
{code:java}
String query = getComponentXPathQuery(clazz) + "/property[@name!='' and 
@value!='']"; {code}
doesn't return the property and it default value and the result is a 
Configuration returning *null*

The simple fix would be to check if the *value* attribute exists via the XPath 
Query in the SCR definition, instead of checking for a non empty value.

A more robust fix would probably be to parse the OCD MetaType (if it is a OCD 
config) and use the *default* attribute which is present over there, see:
{code:java}
<?xml version="1.0" encoding="UTF-8"?>
<metatype:MetaData xmlns:metatype="http://www.osgi.org/xmlns/metatype/v1.2.0"; 
localization="OSGI-INF/l10n/com.sample.website.job.SampleJob$Config">
  <OCD id="com.sample.website.job.SampleJob$Config" name="Sample Configuration" 
description="Sample Configuration Description">
    <AD id="updateImportPath" type="String" name="Sample String Property" 
description="Sample String Property" default=""/>
  </OCD>
  <Designate pid="com.sample.website.job.SampleJob">
    <Object ocdref="com.sample.website.job.SampleJob$Config"/>
  </Designate>
</metatype:MetaData>
{code}
What do you think about this?


> OSGi Mock - Service Registration Designate OCD default empty property is 
> ignored, which leads to NPE
> ----------------------------------------------------------------------------------------------------
>
>                 Key: SLING-12104
>                 URL: https://issues.apache.org/jira/browse/SLING-12104
>             Project: Sling
>          Issue Type: Bug
>          Components: Testing
>    Affects Versions: Testing OSGi Mock 3.3.10
>            Reporter: Robin Brouns
>            Priority: Major
>
> Considering the following sample Class:
> {code:java}
> package com.sample.website.job;
> import org.apache.commons.lang3.StringUtils;
> import org.apache.jackrabbit.oak.commons.PathUtils;
> import org.osgi.service.component.annotations.Activate;
> import org.osgi.service.component.annotations.Component;
> import org.osgi.service.component.annotations.Modified;
> import org.osgi.service.metatype.annotations.AttributeDefinition;
> import org.osgi.service.metatype.annotations.Designate;
> import org.osgi.service.metatype.annotations.ObjectClassDefinition;
> @Component(service = Runnable.class)
> @Designate(ocd = SampleJob.Config.class)
> public class SampleJob implements Runnable {    
>     private String sampleStringProperty;
>     @Activate
>     @Modified
>     public void update(final Config configuration) {
>         this.sampleStringProperty = configuration.sampleStringProperty();
>     }    
>     @Override
>     public void run() {
>         if (PathUtils.isAbsolute(this.sampleStringProperty)) {
>             // do something
>         }
>     }    
>     @ObjectClassDefinition(
>             name = "Sample Configuration",
>             description = "Sample Configuration Description"
>     )
>     @interface Config {        
>         @AttributeDefinition(
>             name = "Sample String Property",
>             description = "Sample String Property"
>         )
>         String sampleStringProperty() default StringUtils.EMPTY;
>     }
> } {code}
> When I try to test this class with the default OSGi configuration via AEM 
> Mocks:
> {code:java}
> final Runnable underTest = 
> aemContext.registerInjectActivateService(SampleJob.class); {code}
> building this class leads to the following SCR definition:
> {code:java}
> <?xml version="1.0" encoding="UTF-8"?>
> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.3.0"; 
> name="com.sample.website.job.SampleJob" activate="update" modified="update">
>   <property name="updateImportPath" type="String" value=""/>
>   <service>
>     <provide interface="java.lang.Runnable"/>
>   </service>
>   <implementation class="com.sample.website.job.SampleJob"/>
> </scr:component>{code}
> the *default* value of *updateImportPath* (an empty String) is *not* injected 
> in the Configuration, but null is being used, which could lead to NPE.
> AEM Mocks uses OSGi Mocks and the following method is used to retrieve the 
> *default* properties and values 
> [https://github.com/apache/sling-org-apache-sling-testing-osgi-mock/blob/c55d97ba266e0630200fcbb378b3f102d2dfba90/core/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java#L292C24-L292C46]
>  
> But as you can see the XPath Query doesn't match with the SCR definition: the 
> property exists with a *name* and there is a {*}value{*}, but it is empty, so:
> {code:java}
> String query = getComponentXPathQuery(clazz) + "/property[@name!='' and 
> @value!='']"; {code}
> doesn't return the property and its default value and the result is a 
> Configuration returning *null*
> The simple fix would be to check if the *value* attribute exists via the 
> XPath Query in the SCR definition, instead of checking for a non empty value.
> A more robust fix would probably be to parse the OCD MetaType (if it is a OCD 
> config) and use the *default* attribute which is present over there, see:
> {code:java}
> <?xml version="1.0" encoding="UTF-8"?>
> <metatype:MetaData xmlns:metatype="http://www.osgi.org/xmlns/metatype/v1.2.0"; 
> localization="OSGI-INF/l10n/com.sample.website.job.SampleJob$Config">
>   <OCD id="com.sample.website.job.SampleJob$Config" name="Sample 
> Configuration" description="Sample Configuration Description">
>     <AD id="updateImportPath" type="String" name="Sample String Property" 
> description="Sample String Property" default=""/>
>   </OCD>
>   <Designate pid="com.sample.website.job.SampleJob">
>     <Object ocdref="com.sample.website.job.SampleJob$Config"/>
>   </Designate>
> </metatype:MetaData>
> {code}
> What do you think about this?



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to