Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Confluence REST API's: Uploading a document to Confluence - JAVA

James Astbury August 28, 2014

Hello,

I am beginning a project where the goal is to upload a document to a folder on my company's confluence site. I have been researching what REST API's and services there are that could help me with my problem. I feel like I have gotten close but am just missing the mark and cannot figure what to do. I have looked through a lot of documentation that has been provided by Atlassian but I have either not been looking in the right place or I just went over something along the way. Can anyone point in the right direction on where I should start? I am attempting to do this within Java. I am new to Confluence and Atlassian so I have no idea if this is possible.

Thanks in advance

3 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

1 vote
Answer accepted
James Astbury September 7, 2014

Tiago and Gorka,

I appreciate both of your assistance. I did figure out how to upload an attachment to a Confluence page in Java. While I didn't use your methods specifically I'll give you both upvotes for your time and because while they didn't quite fit what I was looking for I know it will help someone else out there. And trying both of your methods spurred my thinking and got me going. My method is similar to Bob Swifts method found here: https://bobswift.atlassian.net/secure/attachmentzip/unzip/20314/18100%5B4%5D/confluence-soap-examples/ExampleClientGetServerInfo.java

If you find you are getting weird SSL Exception errors that means you need to add your Confluence's security certificate to your cacerts file. You can find more details on that here: https://confluence.atlassian.com/display/JIRAKB/Unable+to+Connect+to+SSL+Services+due+to+PKIX+Path+Building+Failed+sun.security.provider.certpath.SunCertPathBuilderException

 

Here's what I did:

ConfluenceSoapServiceServiceLocator fConfluenceSoapServiceGetter = new ConfluenceSoapServiceServiceLocator();
ConfluenceSoapService service = null;
String fToken = null;

// This prevents Java from fatal error because it doesn't recognizes Confluence's security certificate. May have to your Confluence sites security certificate to your cacerts file
System.setProperty("jsse.enableSNIExtension", "false");

try {
	// find endpoint on Confluence to work with and get Services from Confluence
	String endPoint = "/plugins/servlet/soap-axis1/confluenceservice-v2";
	fConfluenceSoapServiceGetter.setConfluenceserviceV2EndpointAddress("https://confluence.<companynamehere>.com" + endPoint);
	fConfluenceSoapServiceGetter.setMaintainSession(true);
	service = fConfluenceSoapServiceGetter.getConfluenceserviceV2();
	// Authenticate user
	fToken = service.login(username, password);

	// Read file to be uploaded to Confluence
	FileInputStream fis = null;
	File in = new File(sourceLoc);
	fis = new FileInputStream(in);
	byte[] buf = new byte[4096];
	byte[] fbuf = new byte[(int) in.length()];
	int c = 0;
	int length = 0;
	logger.debug("Reading: " + in.getAbsolutePath());
	while((length = fis.read(buf)) > 0) {
		System.arraycopy(buf, 0, fbuf, c, length);
		c += length;
	}

	// Gather information necessary to upload file
	RemoteAttachment ra = new RemoteAttachment();
	ra.setFileName(reportName);
	ra.setCreator(creator);
	ra.setFileSize(length);
	ra.setContentType("txt");

	// Uploads file to Confluence. PageId is of the page you want to put the attachment on
	service.addAttachment(fToken, pageId, ra, fbuf);
} catch (Exception e) {
	e.printStackTrace();
}
Gorka Puente _Appfire_
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
September 7, 2014

Nice! I'm glad you did it!

azher khan July 21, 2018

help to find out text from confluence 

3 votes
Gorka Puente _Appfire_
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
September 2, 2014

Hi James,

Using what Tiago posted, you can create a POST request from java

User adminUser = userManager.getUser("admin");

ConfluenceUser confluenceAdminUser = new ConfluenceUserImpl(adminUser);
		AuthenticatedUserThreadLocal.set((ConfluenceUser) confluenceAdminUser);
	Request request = requestFactory.createRequest(Request.MethodType.POST, restUrl);
		request.addTrustedTokenAuthentication(); 
		request.execute();

Depending on what you need, you can set the content type or the body of the request

request.setRequestContentType(...);

request.setRequestBody(...);

or even handle the response

request.execute(new ResponseHandler() {
			@Override
			public void handle(Response response) throws ResponseException {
				System.out.println(response.getStatusCode());
			}
		});

Hope this gives you a hint about how to follow!

Gorka

James Astbury September 2, 2014

Thank you for this Gorka. Do you know which jar contains "User" and where I can find that? And is the variable "userManager" of type UserManager? What are the other dependencies for this code?

Gorka Puente _Appfire_
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
September 2, 2014

Hi James,

The jar containing com.atlassian.user.User is atlassian-user-3.0.jar but I think it comes with the core. UserManager has to be injected in your constructor

public YourClass(UserManager userManager){
		this.userManager = userManager;
	}

For the rest of dependencies, I think the following should be enough

atlassian-plugin.xml

	<component-import key="userManager" interface="com.atlassian.sal.api.user.UserManager" />
<component key="compatibilityUserManager" class="com.atlassian.sal.usercompatibility.impl.CompatibilityUserManager" />
  <component-import key="salRequestFactory" interface="com.atlassian.sal.api.net.RequestFactory" />

Your pom.xml

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

...
<properties>
...
<sal.api.version>2.8.0</sal.api.version>
		<usercompatibility.version>0.5</usercompatibility.version>
</properties>


Check it and post the result!

Gorka

James Astbury September 3, 2014

I've never used User or UserManager before and am having some trouble with it. Do you think you could give me a little explanation on them? Not sure how to get it setup. Thanks

Gorka Puente _Appfire_
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
September 3, 2014

Could you be a little more specific? What troubles are you having now?

Gorka

James Astbury September 3, 2014

I get that the adminUser contains credentials for the confluence site I am trying to post to. I do not know how to assign said credentials to the adminUser. It appears it is done with the UserManager but I can't quite figure out how to do it.

Thanks again

Gorka Puente _Appfire_
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
September 3, 2014

Hi James,

In the example I gave to you

User adminUser = userManager.getUser("admin");
 
ConfluenceUser confluenceAdminUser = new ConfluenceUserImpl(adminUser);
        AuthenticatedUserThreadLocal.set((ConfluenceUser) confluenceAdminUser);
    Request request = requestFactory.createRequest(Request.MethodType.POST, restUrl);
        request.addTrustedTokenAuthentication();
        request.execute();

Check this line

AuthenticatedUserThreadLocal.set((ConfluenceUser) confluenceAdminUser);

A simple ThreadLocal to store the currently authenticated user. This can be used when the user comes from something other than the web interface (i.e. SOAP).

Extracted from https://docs.atlassian.com/atlassian-confluence/latest/com/atlassian/confluence/user/AuthenticatedUserThreadLocal.html

Did you try it? If it worked like Tiago said, I suppose it should work this way. You are doing the same, a POST request.

Regards,

Gorka

2 votes
Tiago Comasseto
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 1, 2014

Hi James, have you tried to upload your attachments using this REST call?

curl -D- -u user:password -X POST -H "X-Atlassian-Token: nocheck" -F "file=@test.txt" http://&lt;confluence_url&gt;/rest/api/content/&lt;page_id&gt;/child/attachment

The output of it should be something like this:

HTTP/1.1 100 Continue

HTTP/1.1 100 Continue

HTTP/1.1 200 OK
Date: Tue, 02 Sep 2014 14:21:34 GMT
Server: Apache-Coyote/1.1
X-ASEN: SEN-L4138508
X-Seraph-LoginReason: OK
X-AUSERNAME: admin
X-Content-Type-Options: nosniff
Content-Type: application/json
Set-Cookie: JSESSIONID=6BE16241C81BAAA2F19B7ECBBD4D1A58; Path=/confluence/; HttpOnly
Connection: close
Transfer-Encoding: chunked

{"results":[{"id":"att9797634","type":"attachment","title":"test.txt","version":{"by":{"type":"known","profilePicture":{"path":"/confluence/s/en_GB/5510/701ab0bfc8a95d65a5559a923f8ed8badd272d36.1/_/images/icons/profilepics/default.png","width":48,"height":48,"isDefault":true},"username":"admin","displayName":"Administrator"},"when":"2014-09-02T11:21:34.019-0300","number":1,"minorEdit":false},"container":{"id":"9502724","type":"page","title":"content test","_links":{"webui":"/display/CS/content+test","tinyui":"/x/BACR","self":"https://ironman/confluence/rest/api/content/9502724"},"_expandable":{"history":"/rest/api/content/9502724/history","body":"","container":"","ancestors":"","children":"/rest/api/content/9502724/child","descendants":"/rest/api/content/9502724/descendant","space":"/rest/api/space/CS","version":"","metadata":""}},"metadata":{"mediaType":"application/octet-stream"},"_links":{"download":"/download/attachments/9502724/test.txt?version=1&amp;modificationDate=1409667694019&amp;api=v2","webui":"/pages/viewpageattachments.action?pageId=9502724&amp;highlight=test.txt#content+test-attachment-test.txt","self":"https://ironman/confluence/rest/api/content/att9797634"},"_expandable":{"history":"/rest/api/content/att9797634/history","body":"","ancestors":"","children":"/rest/api/content/att9797634/child","descendants":"/rest/api/content/att9797634/descendant","space":"/rest/api/space/CS"}}],"size":1}

I hope it helps.

Cheers

James Astbury September 1, 2014

I have not, I am actually trying to do this within Java. I did not mention that in the original post, my apologies. I will fix that. Do you know how to do this in Java?

James Astbury September 2, 2014

Tiago, I tried running this and it returned the html of the confluence page. Would you know why this happens?

James Astbury September 2, 2014

I got:

HTTP/1.1 100 Continue

HTTP/1.1 100 Continue

HTTP/1.1 404 Not Found
Tiago Comasseto
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 2, 2014

Do you know what's the http response? for example, in the command output above the response was HTTP/1.1 200 OK, which is the expected one when everything is alright.

Cheers

Tiago Comasseto
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 2, 2014

404 means that your URL wasn't found. In the command line above you'll see the example http://<confluence_url>/rest/api/content/<page_id>/child/attachment, which in my case the actual URL was: https://ironman/confluence/rest/api/content/8814611/child/attachment, you may want to confirm your URL.

Cheers

James Astbury September 2, 2014

I am definitely going wrong with the <confluence_url> portion. To me it seems like it should be the full url of the page I want to upload a document to. But your example only has "ironman/confluence" as the "<confluence_url>". Is there anything you can explain about this portion? I appreciate all the help by the way

James Astbury September 2, 2014

I am also now getting a HTTP 302 response now. Isn't that some form of redirect?

Tiago Comasseto
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 2, 2014

Sure, ironman is a DNS alias (cname) to one of our test servers and the portion "confluence" is a context path that was defined to this confluence instance. So if I want to access Confluence dashboad I'd use https://ironman/confluence

I hope it helps to clarify, let me know if you need any additional info.

Cheers

James Astbury September 2, 2014

So I just don't know enough about these rest services, DNS servers and Confluence but the Confluence instance I am working in is only accessible online through a https://confluence.<companynamehere>.com/display/<destinationfolder>. Based on your previous comment it seems like I can't just use that URL I just put here to complete the CURL command. Does it only work with the DNS alias and context path you have defined? Would I have to do the same thing. I'm sorry if I sound uneducated about this stuff but the truth is I am. I just want to make sure were on the same page and there's not more setup required on my end.

James Astbury September 2, 2014

Yes, this gives me the HTTP 404 as the third HTTP message just like before. Then it spits back the html of that confluence page. I am also using a -k for a parameter because of an issue with the security certificate so I'm just bypassing it. Would that affect anything? Other than that I did exactly what you suggested

James Astbury September 2, 2014

This is the exact command I am using

curl -D- -u <user>:<password> -X POST -H "X-Atlassian-Token: no-check" -F "file=@C:\DEV\TestFile2.txt" https://confluence.<companynameher>.com/rest/api/content/<pageid>/child/attachment-k

Tiago Comasseto
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 2, 2014

Actually it's not necesary to define DNS alias or context path, sorry I may have caused this confusion, my intention was just explain how my URL was built.

Based on your comment it seems that the URL in your curl command should be https://confluence.<companynamehere>.com/rest/api/content/<page_id>/child/attachment, have you tried this format?

TAGS
AUG Leaders

Atlassian Community Events