Unable to compile due to com.atlassian.sal.api.net

Hi,

I have been trying to import classes from com.atlassian.sal.api.net in order to do authentication through application links (between BitBucket and Jira) but have continually run into compilation failures when running atlas-debug, specifically this error:

[ERROR] /C:/AtlasPlugin/plugin/src/main/java/com/atlassian/branchenforce/util/JiraProjects.java:[68,47] cannot find symbol
  symbol:   variable Response
  location: variable response of type com.atlassian.sal.api.net.Response

I have the line specifying the import of the class

`import com.atlassian.sal.api.net.Response;`

The constructor and the Component Import annotation


	private final Response response;
	
	@Inject
	public JiraProjects(@ComponentImport final ApplicationLinkService applicationLinkService, @ComponentImport final Response response)
	{
	   this.applicationLinkService = applicationLinkService;
	   this.response = response;
	}

As well as the dependency in the pom.xml file which was generated when first creating the plugin.

	        <dependency>
	            <groupId>com.atlassian.sal</groupId>
	            <artifactId>sal-api</artifactId>
	            <scope>provided</scope>
	        </dependency>

The only possible thing I can think of is that the version of the SAL api it’s compiling with, is not compatible with the version of BitBucket I’m trying to load when running atlas-debug.

Are there any additional dependencies that should be added? Or a known problem with the SAL api package?

Versions
BitBucket 5.3.2
Jira 7.4.4
Atlassian SDK 6.3.4

Additional versions from pom.xml
<bitbucket.version>5.3.2</bitbucket.version>
<bitbucket.data.version>5.3.2</bitbucket.data.version>
<amps.version>6.3.6</amps.version>
<plugin.testrunner.version>1.2.3</plugin.testrunner.version>
<atlassian.spring.scanner.version>1.2.13</atlassian.spring.scanner.version>

Response isn’t injectable (which you already knew :slight_smile: ).

To get you started properly, let’s create an app that just executes http requests over to Jira from Bitbucket. First we’ll create a service called JiraRemoteConnectionService (because well it will connect to a remote Jira - and I have no imagination) - it has a single method: getContent

@Component
public class JiraRemoteConnectionService
{
    @ComponentImport
    private final ApplicationLinkService applicationLinkService;


    @Inject
    public JiraRemoteConnectionService( final ApplicationLinkService applicationLinkService)
    {
        this.applicationLinkService = applicationLinkService;
    }

    public String getContent(final String url)
    {
        final StringBuffer stringBuffer = new StringBuffer();
        for(final ApplicationLink applicationLink: this.applicationLinkService.getApplicationLinks(JiraApplicationType.class))
        {

            try
            {

                Request request = applicationLink.createImpersonatingAuthenticatedRequestFactory().createRequest(Request.MethodType.GET, url);




                 request.executeAndReturn(new ReturningResponseHandler() {
                    public Object handle(Response response) throws ResponseException
                    {
                        if( response.isSuccessful())
                        {
                            stringBuffer.append( applicationLink.getName());
                            stringBuffer.append("\n");
                            stringBuffer.append(url);
                            stringBuffer.append("\n");
                            stringBuffer.append( response.getResponseBodyAsString());
                            stringBuffer.append("\n\n");


                        }
                        else
                        {
                            stringBuffer.append( response.getStatusCode());
                        }
                        return null;
                    }
                });

            }
            catch(Exception e)
            {
                stringBuffer.append("Error received\n");
            }

        }
        return stringBuffer.toString();
    }
}

The important pieces here is the looping through the applicationLinks that are configured:
for(final ApplicationLink applicationLink: this.applicationLinkService.getApplicationLinks(JiraApplicationType.class))

then we create a Request object:

we can at this point add headers and other “fun” things to the request object, but in this case we’ll just execute it:

                    public Object handle(Response response) throws ResponseException
                    {
....
                    }
      });

To use all of this - I put together a very basic servlet (and wire it up in the Atlassian-plugin.xml):

package demos.servlet;

import demos.api.JiraRemoteConnectionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;

@Scanned
public class DisplayOutPut extends HttpServlet
{
    private static final Logger log = LoggerFactory.getLogger(DisplayOutPut.class);


    private final JiraRemoteConnectionService jiraRemoteConnectionService;

    @Inject
    public DisplayOutPut( final JiraRemoteConnectionService jiraRemoteConnectionService)
    {
        this.jiraRemoteConnectionService = jiraRemoteConnectionService;
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
        resp.setContentType("text/html");
        resp.getWriter().write("<html><head><meta name=\"decorator\" content=\"atl.general\"></head><body>");
        resp.getWriter().write("<h1>Submit a get url</h1>");
        resp.getWriter().write("<form method=\"post\" target=\"other\">");
        resp.getWriter().write("URL: <input type=\"text\" name=\"url\"/>");
        resp.getWriter().write("<input type=\"submit\" value=\"send\"/>");
        resp.getWriter().write("</form>");

        resp.getWriter().write("</body></html>");
    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
        resp.setContentType("text/plain");
        resp.getWriter().write(this.jiraRemoteConnectionService.getContent(req.getParameter("url")));
    }
}

All it does is show a form where you can enter in a url(when you go to http://localhost:7990/bitbucket/plugins/servlet/displayoutput ) and when posted back will execute the getOutput method from the JiraRemoteConnectionService.

Full source is at https://bitbucket.org/dwester42a/example-application-links/src .

Good luck!

1 Like

Oh - I should point out - I used Oauth with impersonation in my application links and verified with the /rest/auth/1/session url .