Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.

Custom OSGi Component behaving oddly

Avatar

Level 3

We are on 6.1, but have not gotten any of the hotfixes installed if that makes a difference (but it is planned for this week).

First off, this works just fine on my local (to my machine) author and publish instances.  On the servers we are seeing the following problem:

So this is a configuration component that I developed as part of our first initial release (which is coming soon).  I have LOGGING applied in the code which I can see being hit on my local machine but cannot see being hit in the publish environment.  I have been able to configure the author environment, but the Publish environment (which is where I really need it) does not take.  My question is based on what is showing on my repository and config screenshots below, why is the component showing as it is in the component screenshot?  Why are my logs not showing when I save and/or startup?

Here's the code for the ContactFormConfigurationServiceImpl activate and modified methods:

@Activate protected void activate(final Map<String, Object> properties) { LOG.info(CLASS_NAME + "activating configuration service"); modified(properties); } @Modified protected void modified(final Map<String, Object> properties) { LOG.info(properties.toString()); fromAddress = PropertiesUtil.toStringArray(properties.get(FROM_EMAIL)); LOG.info(CLASS_NAME + "From: " + fromAddress.length); LOG.info(CLASS_NAME + properties.get(TO_EMAILS)); toAddresses = PropertiesUtil.toStringArray(properties.get(TO_EMAILS)); LOG.info(CLASS_NAME + "To length: " + String.valueOf(toAddresses.length)); standardFolder = PropertiesUtil.toString(properties.get(STANDARD_LEAD_FILE_CREATION_FOLDER), StringUtils.EMPTY); branchFolder = PropertiesUtil.toString(properties.get(BRANCH_LEAD_FILE_CREATION_FOLDER), StringUtils.EMPTY); psrtFolder = PropertiesUtil.toString(properties.get(PRST_LEAD_FILE_CREATION_FOLDER), StringUtils.EMPTY); servicerequestFolder = PropertiesUtil.toString(properties.get(SERVICE_LEAD_FILE_CREATION_FOLDER), StringUtils.EMPTY); }

For what it's worth I did review:

https://docs.adobe.com/docs/en/aem/6-1/deploy/configuring/configuring-osgi.html

12 Replies

Avatar

Level 10

Are you sure it's in an Active State on publish. Once active - you should be getting that log message:

LOG.info(CLASS_NAME + "activating configuration service");

Avatar

Level 10

As @Scott mentioned, first make sure it is hitting @Activate method and logging. If you are not seeing that log itself, then the bundle might not been installed or active on publish instance.

If you are able to see the activate log, next step would be to check the if its logging LOG.info(properties.toString()); and the value of the same.

Let us know your finding.

Also make sure you have 'immediate = true' as mentioned below configure to your component so that it is activated immediately one you install the same.

@Component(immediate = true)

Avatar

Level 3

@Scott, @Lokesh - thanks for your responses.  I got pulled off looking at something else and am just getting back to this one.  So I stopped and started and I am able to see the activate log.  It is pulling null for the value of the properties.get(TO_EMAILS) call (TO_EMAILS is defined as private static final String TO_EMAILS = "to.addresses";).  Because of pulling null it throws an exception where it tries to write out the value of toAddresses.length.

I am still questioning why this would be working fine on my local machine publish but not the server's publish instance.  Should I write a try catch inside of the modified routine?  Is it because it starts out as nulls and it needs to be able to handle that and when it has values it will pull those in the future?

Again, thanks for your help.

Avatar

Level 10

that means to.addressess is not configured in publish instance. Put in some values and it should not throw null pointer else you will have to check for null before reading any configuration if its not mandatory !

Avatar

Level 3

@Lokesh - K, I updated to handle the null value more gracefully.  I now appear to be making it all of the way through my activate routine.  I tried editing the values inside of :4503/system/console/configMgr three different times and none of those times did I seem to be hitting my modified routine even though the values are updating.  Any ideas?  Why are they not being pulled from the repository (screenshot) on first post?  Thanks.

Avatar

Level 3

@Lokesh - PropertiesUtil is just the standard org.apache.sling.commons.osgi.PropertiesUtil;

@Scott - Thanks for that, based on that blog post I have updated my declaration to be more correct.  That said, it is still not working.  I did try just creating a sling:OsgiConfig node which worked (in the sense that I can see it under system/console/configMgr, but not under /system/console/components, is that the way it is supposed to work?).  Could I code a fallback to attempt to read from the property I created using the How to Read Property - Using generic class option from the blog post if I cannot pull from the existing method?

Just to make sure that I am not missing something obvious, here's the (new and improved) code for the whole class:

@Service(value = ContactFormConfigurationServiceImpl.class) @Component(immediate = true, metatype = true, label = "Contact Form Configuration Service") public class ContactFormConfigurationServiceImpl implements ContactFormConfigurationService { private static final Logger LOG = LoggerFactory.getLogger(ContactFormConfigurationServiceImpl.class); private static final String CLASS_NAME = "[ContactFormConfigurationService]: "; @Property(unbounded = PropertyUnbounded.ARRAY, label = "From Address", cardinality = 50, description = "Formatting: ALIAS-emailAddress1") private static final String FROM_EMAIL = "from.address"; @Property(unbounded = PropertyUnbounded.ARRAY, label = "To Addresses", cardinality = 100, description = "Formatting: LISTNAME-emailAddress1;emailAddress2;emailAddress3;etc") private static final String TO_EMAILS = "to.addresses"; @Property(unbounded = PropertyUnbounded.DEFAULT, label = "Standard Lead File Creation Folder", description = "The folder where standard leads are created") private static final String STANDARD_LEAD_FILE_CREATION_FOLDER = "standard.folder"; @Property(unbounded = PropertyUnbounded.DEFAULT, label = "Branch Lead File Creation Folder", description = "The folder where branch leads are created") private static final String BRANCH_LEAD_FILE_CREATION_FOLDER = "branch.folder"; @Property(unbounded = PropertyUnbounded.DEFAULT, label = "PSRT Lead File Creation Folder", description = "The folder where PSRT leads are created") private static final String PRST_LEAD_FILE_CREATION_FOLDER = "psrt.folder"; @Property(unbounded = PropertyUnbounded.DEFAULT, label = "Service Lead File Creation Folder", description = "The folder where service leads are created") private static final String SERVICE_LEAD_FILE_CREATION_FOLDER = "servicerequest.folder"; private String[] fromAddress; private String[] toAddresses; private String standardFolder; private String branchFolder; private String psrtFolder; private String servicerequestFolder; @Override public String[] getFromAddresses() { return fromAddress; } @Override public String[] getToAddresses() { return toAddresses; } @Override public String getStandardFolder() { return standardFolder; } @Override public String getBranchFolder() { return branchFolder; } @Override public String getPsrtFolder() { return psrtFolder; } @Override public String getServicerequestFolder() { return servicerequestFolder; } @Activate protected void activate(final Map<String, Object> properties) { LOG.info(CLASS_NAME + "activating configuration service"); modified(properties); } @Modified protected void modified(final Map<String, Object> properties) { LOG.info(properties.toString()); fromAddress = PropertiesUtil.toStringArray(getPropertyValue(properties, FROM_EMAIL)); LOG.info(CLASS_NAME + "From: " + fromAddress.length); toAddresses = PropertiesUtil.toStringArray(getPropertyValue(properties, TO_EMAILS)); LOG.info(CLASS_NAME + "To length: " + String.valueOf(toAddresses.length)); standardFolder = PropertiesUtil.toString(properties.get(STANDARD_LEAD_FILE_CREATION_FOLDER), StringUtils.EMPTY); branchFolder = PropertiesUtil.toString(properties.get(BRANCH_LEAD_FILE_CREATION_FOLDER), StringUtils.EMPTY); psrtFolder = PropertiesUtil.toString(properties.get(PRST_LEAD_FILE_CREATION_FOLDER), StringUtils.EMPTY); servicerequestFolder = PropertiesUtil.toString(properties.get(SERVICE_LEAD_FILE_CREATION_FOLDER), StringUtils.EMPTY); } private Object getPropertyValue(final Map<String, Object> properties, String fieldToPull) { Object val = properties.get(fieldToPull); if (val == null) { val = StringUtils.EMPTY; } return val; } }

Thanks again for your help.

Avatar

Level 10

Can you please package up your code under /apps and email them to me at scottm@adobe.com. Send me the ZIP. Also place the OSGi under OSGi under apps. I want to debug into this and see what is happening. Also - we need a good community article on this use case too. With the code - i will get to the bottom of this. 

Avatar

Level 10

have you pushed 'config' folder to publish instance ?

Avatar

Level 10

this does not make sense - you are seeing config values working fine on Author - but on Pub they are defined but returning null. 

Look at this article - there are different ways to specify config settings. Try using another way and see what happens. 

http://www.wemblog.com/2012/10/how-to-work-with-configurations-in-cq.html

Avatar

Level 10

We wrote an article on this use case and the code works on both Author and Publish. We defined config values in CRXDE Lite and an OSGi bundle. When the OSGi bundle is deployed on both Pub and Auth and the Config values are located on both /app/system in Auth and Pub - the values are read successfully.

29.10.2015 12:19:25.000 *INFO* [qtp19926589-181] org.testsite.core.service.impl.ConfigurationServiceImpl [*** AEM ConfigurationService]: activating configuration service

29.10.2015 12:19:25.000 *INFO* [qtp19926589-181] org.testsite.core.service.impl.ConfigurationServiceImpl {service.pid=org.testsite.core.service.impl.ConfigurationServiceImpl, multifield=[Ljava.lang.String;@12b5904, simplefield=simple config author, component.name=org.testsite.core.service.impl.ConfigurationServiceImpl, component.id=2200}

29.10.2015 12:19:25.000 *INFO* [qtp19926589-181] org.testsite.core.service.impl.ConfigurationServiceImpl Mutli String Size: 3

29.10.2015 12:19:25.000 *INFO* [qtp19926589-181] org.testsite.core.service.impl.ConfigurationServiceImpl Simple String: simple config author

To read this article -- see Reading AEM OSGi Configuration Values.