Problem injecting active objects service

Hi all
I’ve created AO service class in my plugin that works fine when injected in webwork class (CRUD functions working as expected).
but when I try to inject it to another class besides of webwork, injection fails unless I remove @Transactional annotation from AO service interface.
appreciate any hint to get it work.

that’s AO interface

import com.atlassian.activeobjects.tx.Transactional;
import ru.homecredit.jiraadapter.entities.FieldsGroupSettings;
import ru.homecredit.jiraadapter.entities.FieldsGroupSettingsRaw;

import java.util.List;
import java.util.Optional;

@Transactional
public interface SettingsService {
    String add(String description, String[] fieldsKeys, String[] usersKeys);
    List<FieldsGroupSettings> all();
    String delete(int id);
    String edit(int id, String description, String[] fieldsKeys, String[] usersKeys);
    List<String> getAllCustomFieldsKeys();
    List<String>  getAllUsers();
    Optional<FieldsGroupSettingsRaw> getById(int id);
    boolean isPermittedToEdit(String fieldKey);
    String prettyString(FieldsGroupSettings fieldsGroupSettingsRaw);
}

that’s its implementation class constructor

import com.atlassian.activeobjects.external.ActiveObjects;
import com.atlassian.jira.bc.user.search.UserSearchParams;
import com.atlassian.jira.bc.user.search.UserSearchService;
import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.user.ApplicationUser;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import lombok.extern.slf4j.Slf4j;
import ru.homecredit.jiraadapter.entities.FieldsGroupSettings;
import ru.homecredit.jiraadapter.entities.FieldsGroupSettingsRaw;

import javax.inject.Inject;
import javax.inject.Named;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Named
@Slf4j
public class SettingsServiceImpl implements SettingsService {
private final ActiveObjects activeObjects;
private final UserSearchService userSearchService;
private final CustomFieldManager customFieldManager;
private final UserSearchParams userSearchParams
        = (new UserSearchParams.Builder())
        .allowEmptyQuery(true)
        .includeActive(true)
        .includeInactive(true)
        .maxResults(100000).build();

    @Inject
    public SettingsServiceImpl(@ComponentImport ActiveObjects activeObjects,
                               @ComponentImport UserSearchService userSearchService,
                               @ComponentImport CustomFieldManager customFieldManager) {
        this.activeObjects = activeObjects;
        this.userSearchService = userSearchService;
        this.customFieldManager = customFieldManager;
    }

that’s the webworks constructor where the service is being injected perfectly and works well

import com.atlassian.jira.web.action.JiraWebActionSupport;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import ru.homecredit.jiraadapter.entities.FieldsGroupSettings;
import ru.homecredit.jiraadapter.service.SettingsServiceImpl;

import java.util.List;

@Getter
@Setter
@RequiredArgsConstructor
@Slf4j
public class FieldsSettingsWebwork extends JiraWebActionSupport {
    private final SettingsServiceImpl settingsService;
    private List<String> allCustomFieldsKeys;
    private List<String> savedCustomFieldsKeys;
    private String[] customFieldsKeysToSave;
    private List<String> allUsers;
    private List<String> savedUsers;
    private String[] usersToSave;
    private List<FieldsGroupSettings> currentSettings;
    private String groupID;
    private String description;
    private String message ="";

and thats the business class where service injection fails unless @Transactional annotation is removed from service interface

import com.atlassian.jira.issue.context.IssueContext;
import com.atlassian.jira.issue.context.IssueContextImpl;
import com.atlassian.jira.issue.customfields.manager.OptionsManager;
import com.atlassian.jira.issue.customfields.option.Option;
import com.atlassian.jira.issue.customfields.option.Options;
import com.atlassian.jira.issue.fields.ConfigurableField;
import com.atlassian.jira.issue.fields.FieldManager;
import com.atlassian.jira.issue.fields.config.FieldConfig;
import com.atlassian.jira.project.Project;
import com.atlassian.jira.project.ProjectManager;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import lombok.extern.slf4j.Slf4j;
import ru.homecredit.jiraadapter.dto.FieldOptions;
import ru.homecredit.jiraadapter.dto.FieldParameters;
import ru.homecredit.jiraadapter.dto.request.FieldOptionsRequest;

import javax.inject.Inject;
import javax.inject.Named;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Named
public class FieldInitializationService {
    private final FieldManager fieldManager;
    private final ProjectManager projectManager;
    private final OptionsManager optionsManager;
    private final SettingsServiceImpl settingsService;

    @Inject
    public FieldInitializationService(@ComponentImport FieldManager fieldManager,
                                      @ComponentImport ProjectManager projectManager,
                                      @ComponentImport OptionsManager optionsManager
                                      ,@ComponentImport SettingsServiceImpl settingsService
                                    ) {
        this.fieldManager = fieldManager;
        this.projectManager = projectManager;
        this.optionsManager = optionsManager;
        this.settingsService = settingsService;
    }

Hi Ignat,

There’s a few things to notice regarding your code:

  1. Why in FieldInitializationService you’re injecting implementation of SettingsService instead of interface itself?
  2. You don’t need to mark your own classes with @ComponentImport annotation. This likely leads to errors.
  3. It looks like @Transaction annotation is not implemented in Jira.

Hi, Alexey. Nice to meet you here.

  1. Interface just is not being injected in atlassian framework in my case (but injects perfectly in spring boot projects) I regard it as some “strangeness” of atlassian sdk. Anyway - JiraAdapterSettingsServiceImpl injects well and works as expected in the same class FieldInitializationService
  2. That’s the random thing I tried to make it work. removing of this annotation does not make any difference
  3. That’s why I do not use it and use @Transactional which does work in jira in accordance with this tutorial

the most strange thing for me is that SettingsServiceImpl injects to FieldsSettingsWebwork and works well there, but fails to inject to FieldsInitializationService

P.S.: I’ve tried to put @Named annotation to FieldsSettingWebwork and injection starts to fail. So - SettingsService is being injected only to classes not annotated with @Named

Further investigation showed, that this is clearly some sdk or dev env bug.
plugin builds and behaves properly after uninstalling it from Jira add-ons menu, stopping and executing atlas-run once again.
If problem come back after quick reload (and it does sometimes), these steps should be repeated.