Getting class cast exception for serviceDeskService.getServiceDeskForProject()

Hi,

I am trying to get servicedesk object with following line

import com.atlassian.servicedesk.api.ServiceDeskService;

ServiceDeskService serviceDeskService=ComponentAccessor.getOSGiComponentInstanceOfType(ServiceDeskService.class);
Either<AnError, ServiceDesk> sd = serviceDeskService.getServiceDeskForProject(loggedInUser, helpdeskObj);

the above line giving the following error, not sure how to resolve this
[o.a.c.c.C.[.[localhost].[/].[action]] Servlet.service() for servlet [action] in context with path [] threw exception [java.lang.IllegalStateException: Unable to resolve component: interface com.atlassian.servicedesk.api.ServiceDeskService] with root cause
java.lang.ClassCastException: Cannot cast com.atlassian.servicedesk.internal.feature.servicedesk.ServiceDeskServiceImpl to com.atlassian.servicedesk.api.ServiceDeskService
at java.lang.Class.cast(Class.java:3369)
at com.atlassian.jira.plugin.OsgiServiceTrackerCacheImpl.getOsgiComponentOfType(OsgiServiceTrackerCacheImpl.java:65)

How are you importing the ServiceDeskService into you class? Are you doing <component-import or are you using spring-scanner?

I am using Spring scanner , first I tried with @ComponentImport and @Autowired annotations with this I got following error

threw exception [org.springframework.aop.AopInvocationException: AOP configuration seems to be invalid: tried calling method [public abstract com.atlassian.fugue.Either com.atlassian.servicedesk.api.ServiceDeskService.getServiceDeskForProject(com.atlassian.jira.user.ApplicationUser,com.atlassian.jira.project.Project)] on target [com.atlassian.servicedesk.internal.feature.servicedesk.ServiceDeskServiceImpl@3db2c2a0]; nested exception is java.lang.IllegalArgumentException: object is not an instance of declaring class] with root cause
java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)

Can you paste in your service desk dependency from the Pom.xml as well as your package-import statement?

Package import: import com.atlassian.servicedesk.api.ServiceDeskService;

pom.xml:

com.atlassian.jira jira-api ${jira.version} provided
	<dependency>
		<groupId>com.atlassian.jira</groupId>
		<artifactId>jira-core</artifactId>
		<version>${jira.version}</version>
		<scope>provided</scope>
	</dependency>

	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.10</version>
		<scope>test</scope>
	</dependency>

	<dependency>
		<groupId>com.atlassian.plugin</groupId>
		<artifactId>atlassian-spring-scanner-annotation</artifactId>
		<version>${atlassian.spring.scanner.version}</version>
		<scope>provided</scope>
	</dependency>
	
	 <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${springframework.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.atlassian.pocketknife</groupId>
        <artifactId>atlassian-pocketknife-api-commons-jira</artifactId>
        <version>${pocketknife.api.commons.version}</version>
        <scope>provided</scope>
    </dependency>
	
	 <dependency>
        <groupId>com.atlassian.fugue</groupId>
        <artifactId>fugue</artifactId>
        <version>${fugue.version}</version>
        <scope>provided</scope>
    </dependency>

	<!-- <dependency>
		<groupId>com.atlassian.plugin</groupId>
		<artifactId>atlassian-spring-scanner-runtime</artifactId>
		<version>${atlassian.spring.scanner.version}</version>
		<scope>runtime</scope>
	</dependency> -->

	<dependency>
		<groupId>javax.inject</groupId>
		<artifactId>javax.inject</artifactId>
		<version>1</version>
		<scope>provided</scope>
	</dependency>

	<!-- WIRED TEST RUNNER DEPENDENCIES -->
	<dependency>
		<groupId>com.atlassian.plugins</groupId>
		<artifactId>atlassian-plugins-osgi-testrunner</artifactId>
		<version>${plugin.testrunner.version}</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>javax.ws.rs</groupId>
		<artifactId>jsr311-api</artifactId>
		<version>1.1.1</version>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>com.google.code.gson</groupId>
		<artifactId>gson</artifactId>
		<version>2.2.2-atlassian-1</version>
	</dependency>

	<!-- Uncomment to use TestKit in your project. Details at https://bitbucket.org/atlassian/jira-testkit -->
	<!-- You can read more about TestKit at https://developer.atlassian.com/display/JIRADEV/Plugin+Tutorial+-+Smarter+integration+testing+with+TestKit -->
	<!-- <dependency> <groupId>com.atlassian.jira.tests</groupId> <artifactId>jira-testkit-client</artifactId> 
		<version>${testkit.version}</version> <scope>test</scope> </dependency> -->

	<dependency>
		<groupId>com.atlassian.templaterenderer</groupId>
		<artifactId>atlassian-template-renderer-api</artifactId>
		<version>3.0.0</version>
		<scope>provided</scope>
	</dependency>
	
	<dependency>
		<groupId>com.atlassian.servicedesk</groupId>
		<artifactId>jira-servicedesk-api</artifactId>
		<version>${jira.servicedesk.application.version}</version>
	</dependency>

</dependencies>

<build>
	<plugins>
		<plugin>
			<groupId>com.atlassian.maven.plugins</groupId>
			<artifactId>maven-jira-plugin</artifactId>
			<version>${amps.version}</version>
			<extensions>true</extensions>
			<configuration>
				<productVersion>${jira.version}</productVersion>
				<productDataVersion>${jira.version}</productDataVersion>
				<!-- Uncomment to install TestKit backdoor in JIRA. -->
				<!-- <pluginArtifacts> <pluginArtifact> <groupId>com.atlassian.jira.tests</groupId> 
					<artifactId>jira-testkit-plugin</artifactId> <version>${testkit.version}</version> 
					</pluginArtifact> </pluginArtifacts> -->
				<enableQuickReload>true</enableQuickReload>
				<enableFastdev>false</enableFastdev>

				<!-- See here for an explanation of default instructions: -->
				<!-- https://developer.atlassian.com/docs/advanced-topics/configuration-of-instructions-in-atlassian-plugins -->
				<instructions>
					<Atlassian-Plugin-Key>${atlassian.plugin.key}</Atlassian-Plugin-Key>

					<!-- Add package to export here -->
					<Export-Package>
						com.acis.ITSM.portal.api,
					</Export-Package>

					<!-- Add package import here -->
					<Import-Package>							
						*;version="0";resolution:=optional
					</Import-Package>

					<!-- Ensure plugin is spring powered -->
					<Spring-Context>*</Spring-Context>
				</instructions>
				 <skipManifestValidation>true</skipManifestValidation>
			</configuration>
		</plugin>

		<plugin>
			<groupId>com.atlassian.plugin</groupId>
			<artifactId>atlassian-spring-scanner-maven-plugin</artifactId>
			<version>${atlassian.spring.scanner.version}</version>
			<executions>
				<execution>
					<goals>
						<goal>atlassian-spring-scanner</goal>
					</goals>
					<phase>process-classes</phase>
				</execution>
			</executions>
			<configuration>
				<scannedDependencies>
					<dependency>
						<groupId>com.atlassian.plugin</groupId>
						<artifactId>atlassian-spring-scanner-external-jar</artifactId>
					</dependency>
				</scannedDependencies>
				<verbose>flase</verbose>
			</configuration>
		</plugin>
	</plugins>
	<pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

<properties>
	<jira.version>7.8.2</jira.version>
	<amps.version>6.3.15</amps.version>
	<jira.servicedesk.application.version>3.9.1</jira.servicedesk.application.version>
	<atlassian.spring.scanner.version>2.1.5</atlassian.spring.scanner.version>
	<plugin.testrunner.version>1.2.3</plugin.testrunner.version>
	<springframework.version>5.0.5.RELEASE</springframework.version>
    <pocketknife.api.commons.version>0.21.1</pocketknife.api.commons.version>
    <fugue.version>2.6.0</fugue.version>
	
	<!-- This key is used to keep the consistency between the key in atlassian-plugin.xml 
		and the key to generate bundle. -->
	<atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>
	<!-- TestKit version 6.x for JIRA 6.x -->
	<testkit.version>6.3.11</testkit.version>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<maven.compiler.source>1.8</maven.compiler.source>
	<maven.compiler.target>1.8</maven.compiler.target>
</properties>

Change:


	<dependency>
		<groupId>com.atlassian.servicedesk</groupId>
		<artifactId>jira-servicedesk-api</artifactId>
		<version>${jira.servicedesk.application.version}</version>
	</dependency>

to:


	<dependency>
		<groupId>com.atlassian.servicedesk</groupId>
		<artifactId>jira-servicedesk-api</artifactId>
		<version>${jira.servicedesk.application.version}</version>
               <scope>provided</scope>
	</dependency>

That way you’re not bundling JSD with your app :slight_smile:

Also - in:

					<Import-Package>							
						*;version="0";resolution:=optional
					</Import-Package>
``
Add:
				<Import-Package>				
					com.atlassian.servicedesk.api.*;resolution:=optional,
					*;version="0";resolution:=optional
				</Import-Package>

In theory the * should take care of it - but I've found it's safer to explicitly to call it. Then use @ComponentImport on the service so that spring scanner will create the appropriate marker files (so you don't have to use ComponentAccessor.
1 Like

Thanks for your response!

I made changes as follows then it worked, we have to use api version instead of application version

<dependency>
        <groupId>com.atlassian.servicedesk</groupId>
        <artifactId>jira-servicedesk-api</artifactId>
        <version>${jira-servicedesk-api.version}</version>
        <scope>provided</scope>
    </dependency>