Does anyone have any examples on how to create a page/wiki entry in Confluence using Confluence's RESTful API? I'm trying to write something in Java that can do this.
Thank you in advance...
Thank you, I already checked the documentation online but I couldn't find any examples THAT USE JAVA in the Confluence REST API. That's why I posted on here.
Regardless, I think I figured it out:
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
/**
* Creates a Confluence wiki page via the RESTul API
* using an HTTP Post command.
*/
public class ConfluenceRestApi2CreateEntry {
//private static final String BASE_URL = "http://localhost:1990/confluence";
private static final String BASE_URL = "https://<context>.atlassian.net/wiki";
private static final String USERNAME = "username";
private static final String PASSWORD = "password";
private static final String ENCODING = "utf-8";
public static String createContentRestUrl()throws UnsupportedEncodingException
{
return String.format("%s/rest/api/content/?&os_authType=basic&os_username=%s&os_password=%s", BASE_URL, URLEncoder.encode(USERNAME, ENCODING), URLEncoder.encode(PASSWORD, ENCODING));
}
public static void main(final String[] args) throws Exception
{
String wikiPageTitle = "My Awesome Page";
String wikiPage = "<h1>Things That Are Awesome</h1><ul><li>Birds</li><li>Mammals</li><li>Decapods</li></ul>";
String wikiSpace = "JOUR";
String labelToAdd = "awesome_stuff";
int parentPageId = 9994250;
JSONObject newPage = defineConfluencePage(wikiPageTitle,
wikiPage,
wikiSpace,
labelToAdd,
parentPageId);
createConfluencePageViaPost(newPage);
}
public static void createConfluencePageViaPost(JSONObject newPage) throws Exception
{
HttpClient client = new DefaultHttpClient();
// Send update request
HttpEntity pageEntity = null;
try
{
//2016-12-18 - StirlingCrow: Left off here. Was finally able to get the post command to work
//I can begin testing adding more data to the value stuff (see above)
HttpPost postPageRequest = new HttpPost(createContentRestUrl());
StringEntity entity = new StringEntity(newPage.toString(), ContentType.APPLICATION_JSON);
postPageRequest.setEntity(entity);
HttpResponse postPageResponse = client.execute(postPageRequest);
pageEntity = postPageResponse.getEntity();
System.out.println("Push Page Request returned " + postPageResponse.getStatusLine().toString());
System.out.println("");
System.out.println(IOUtils.toString(pageEntity.getContent()));
}
finally
{
EntityUtils.consume(pageEntity);
}
}
public static JSONObject defineConfluencePage(String pageTitle,
String wikiEntryText,
String pageSpace,
String label,
int parentPageId) throws JSONException
{
//This would be the command in Python (similar to the example
//in the Confluence example:
//
//curl -u <username>:<password> -X POST -H 'Content-Type: application/json' -d'{
// "type":"page",
// "title":"My Awesome Page",
// "ancestors":[{"id":9994246}],
// "space":{"key":"JOUR"},
// "body":
// {"storage":
// {"value":"<h1>Things That Are Awesome</h1><ul><li>Birds</li><li>Mammals</li><li>Decapods</li></ul>",
// "representation":"storage"}
// },
// "metadata":
// {"labels":[
// {"prefix":"global",
// "name":"journal"},
// {"prefix":"global",
// "name":"awesome_stuff"}
// ]
// }
// }'
// http://localhost:8080/confluence/rest/api/content/ | python -mjson.tool
JSONObject newPage = new JSONObject();
// "type":"page",
// "title":"My Awesome Page"
newPage.put("type","page");
newPage.put("title", pageTitle);
// "ancestors":[{"id":9994246}],
JSONObject parentPage = new JSONObject();
parentPage.put("id",parentPageId);
JSONArray parentPageArray = new JSONArray();
parentPageArray.put(parentPage);
newPage.put("ancestors", parentPageArray);
// "space":{"key":"JOUR"},
JSONObject spaceOb = new JSONObject();
spaceOb.put("key",pageSpace);
newPage.put("space", spaceOb);
// "body":
// {"storage":
// {"value":"<p><h1>Things That Are Awesome</h1><ul><li>Birds</li><li>Mammals</li><li>Decapods</li></ul></p>",
// "representation":"storage"}
// },
JSONObject jsonObjects = new JSONObject();
jsonObjects.put("value", wikiEntryText);
jsonObjects.put("representation","storage");
JSONObject storageObject = new JSONObject();
storageObject.put("storage", jsonObjects);
newPage.put("body", storageObject);
//LABELS
// "metadata":
// {"labels":[
// {"prefix":"global",
// "name":"journal"},
// {"prefix":"global",
// "name":"awesome_stuff"}
// ]
// }
JSONObject prefixJsonObject1 = new JSONObject();
prefixJsonObject1.put("prefix","global");
prefixJsonObject1.put("name","journal");
JSONObject prefixJsonObject2 = new JSONObject();
prefixJsonObject2.put("prefix","global");
prefixJsonObject2.put("name",label);
JSONArray prefixArray = new JSONArray();
prefixArray.put(prefixJsonObject1);
prefixArray.put(prefixJsonObject2);
JSONObject labelsObject = new JSONObject();
labelsObject.put("labels", prefixArray);
newPage.put("metadata",labelsObject);
return newPage;
}
}
Here's a project in GitHub that I created that also has an example of simply pulling wiki page entry using Java:
https://github.com/stirlingcrow/Confluence-AccessRestApiWithJava
What about using the official REST client?
https://mvnrepository.com/artifact/com.atlassian.confluence/confluence-rest-client
I'm not able to find any documentation on how to use it, tho.
Related
I am using Google Bigquery V2 Java API. I am not able to find a way to get query results in JSON format.
In Bigquery Web UI we can see this JSON and Table form of results. see scrrenshot.
Is there any way to get the GetQueryResultsResponse as JSON, using Java API.
One option is to apply the TO_JSON_STRING function to the results of your query. For example,
#standardSQL
SELECT TO_JSON_STRING(t)
FROM (
SELECT x, y
FROM YourTable
WHERE z = 10
) AS t;
If you want all of the table's columns as JSON, you can use a simpler form:
#standardSQL
SELECT TO_JSON_STRING(t)
FROM YourTable AS t
WHERE z = 10;
I'm using a service account to access the BigQuery REST API to get the response in JSON format.
In order to use a service account, you will have to go to credentials (https://console.cloud.google.com/apis/credentials) and choose a project.
You will get a drop down like this:
Create a Service account for your project and download the secret file in the JSON format. Keep the JSON file in your file system and set the path to it. Check below image to set the file path:
So, now all you have to do in is use JAVA client api to consume the Big Query REST API.
Here's is a simple solution that I've been using for my project.
package com.example.bigquery;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import org.apache.log4j.Logger;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpContent;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.http.json.JsonHttpContent;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.common.io.CharStreams;
public class BigQueryDemo {
private static final String QUERY_URL_FORMAT = "https://www.googleapis.com/bigquery/v2/projects/%s/queries" + "?access_token=%s";
private static final String QUERY = "query";
private static final String QUERY_HACKER_NEWS_COMMENTS = "SELECT * FROM [bigquery-public-data:hacker_news.comments] LIMIT 1000";
private static final Logger logger = Logger.getLogger(BigQueryDemo.class);
static GoogleCredential credential = null;
static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
static final JsonFactory JSON_FACTORY = new JacksonFactory();
static {
// Authenticate requests using Google Application Default credentials.
try {
credential = GoogleCredential.getApplicationDefault();
credential = credential.createScoped(Arrays.asList("https://www.googleapis.com/auth/bigquery"));
credential.refreshToken();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void implicit() {
String projectId = credential.getServiceAccountProjectId();
String accessToken = generateAccessToken();
// Set the content of the request.
Dataset dataset = new Dataset().addLabel(QUERY, QUERY_HACKER_NEWS_COMMENTS);
HttpContent content = new JsonHttpContent(JSON_FACTORY, dataset.getLabels());
// Send the request to the BigQuery API.
GenericUrl url = new GenericUrl(String.format(QUERY_URL_FORMAT, projectId, accessToken));
logger.debug("URL: " + url.toString());
String responseJson = getQueryResult(content, url);
logger.debug(responseJson);
}
private static String getQueryResult(HttpContent content, GenericUrl url) {
String responseContent = null;
HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory();
HttpRequest request = null;
try {
request = requestFactory.buildPostRequest(url, content);
request.setParser(JSON_FACTORY.createJsonObjectParser());
request.setHeaders(
new HttpHeaders().set("X-HTTP-Method-Override", "POST").setContentType("application/json"));
HttpResponse response = request.execute();
InputStream is = response.getContent();
responseContent = CharStreams.toString(new InputStreamReader(is));
} catch (IOException e) {
logger.error(e);
}
return responseContent;
}
private static String generateAccessToken() {
String accessToken = null;
if ((System.currentTimeMillis() > credential.getExpirationTimeMilliseconds())) {
accessToken = credential.getRefreshToken();
} else {
accessToken = credential.getAccessToken();
}
System.out.println(accessToken);
return accessToken;
}
}
Following is the Github link to the code: https://github.com/vslala/BigQueryRestSample
It is just a demo project to fetch JSON data from the BQ REST API. Do not use it in your project directly.
Let me know if you have any questions.
I'm having this error :
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
ContentModel cannot be resolved to a variable
at test2CMIS.Test.main(Test.java:39)"
And I dont understand from where it comes, here is my code :
public class Test {
public static void main(String[] args){
Test atest = new Test();
Session session = atest.iniSession();
AuthenticationService authenticationService=null;
PersonService personService = null;
if (authenticationService.authenticationExists("test") == false)
{
authenticationService.createAuthentication("test", "changeMe".toCharArray());
PropertyMap ppOne = new PropertyMap(4);
ppOne.put(ContentModel.PROP_USERNAME, "test");
ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName");
ppOne.put(ContentModel.PROP_LASTNAME, "lastName");
ppOne.put(ContentModel.PROP_EMAIL, "test"+"#example.com");
personService.createPerson(ppOne);
}
}
I did import the : import org.alfresco.model.ContentModel; and a lot of others librarys for my code.
Thx for help.
The code I'm using and I left some things that I tried too in comments so you can see what things I have done:
import java.io.File;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import org.alfresco.service.cmr.security.*;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import java.util.Iterator;
import org.alfresco.repo.jscript.People;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.PropertyMap;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.client.api.Document;
import org.apache.chemistry.opencmis.client.api.Folder;
import org.apache.chemistry.opencmis.client.api.Session;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.SessionParameter;
import org.apache.chemistry.opencmis.commons.enums.BindingType;
import org.apache.chemistry.opencmis.commons.enums.VersioningState;
import org.apache.chemistry.opencmis.commons.exceptions.CmisContentAlreadyExistsException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisUnauthorizedException;
import org.apache.chemistry.opencmis.client.util.FileUtils;
import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl;
public class Test {
public static void main(String[] args){
Test atest = new Test();
Session session = atest.iniSession();
AuthenticationService authenticationService=new AuthenticationServiceImpl();
PersonService personService = new PersonServiceImpl();
HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
properties.put(ContentModel.PROP_USERNAME, "test");
properties.put(ContentModel.PROP_FIRSTNAME, "test");
properties.put(ContentModel.PROP_LASTNAME, "qsdqsd");
properties.put(ContentModel.PROP_EMAIL, "wshAlors#gmail.com");
properties.put(ContentModel.PROP_ENABLED, Boolean.valueOf(true));
properties.put(ContentModel.PROP_ACCOUNT_LOCKED, Boolean.valueOf(false));
personService.createPerson(properties);
authenticationService.createAuthentication("test", "changeme".toCharArray());
authenticationService.setAuthenticationEnabled("test", true);
authenticationService.getAuthenticationEnabled("Admin");
//String testAuthen = authenticationService.getCurrentTicket();
//System.out.println(testAuthen);
//QName username = QName.createQName("test");
//Map<QName,Serializable> propertiesUser = new HashMap<QName,Serializable>();
//propertiesUser.put(ContentModel.PROP_USERNAME,username);
//propertiesUser.put(ContentModel.PROP_FIRSTNAME,"test");
//propertiesUser.put(ContentModel.PROP_LASTNAME,"test");
//propertiesUser.put(ContentModel.PROP_EMAIL, "test#example.com");
//propertiesUser.put(ContentModel.PROP_PASSWORD,"0000");
//personService.createPerson(propertiesUser);
//if (authenticationService.authenticationExists("test") == false)
//{
// authenticationService.createAuthentication("test", "changeMe".toCharArray());
// PropertyMap ppOne = new PropertyMap(4);
// ppOne.put(ContentModel.PROP_USERNAME, "test");
// ppOne.put(ContentModel.PROP_FIRSTNAME, "test");
// ppOne.put(ContentModel.PROP_LASTNAME, "test");
// ppOne.put(ContentModel.PROP_EMAIL, "test#example.com");
//ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle");
// personService.createPerson(ppOne);
//}
}
public Session iniSession() {
Session session;
SessionFactoryImpl sf = SessionFactoryImpl.newInstance();
Map<String, String> parameters = new HashMap<String, String>();
Scanner reader = new Scanner(System.in);
System.out.println("Enter your logging : ");
String log = reader.nextLine();
System.out.println("Enter your password : ");
String pass = reader.nextLine();
parameters.put(SessionParameter.USER, log);
parameters.put(SessionParameter.PASSWORD, pass);
parameters.put(SessionParameter.BROWSER_URL, "http://127.0.0.1:8080/alfresco/api/-default-/public/cmis/versions/1.1/browser");
parameters.put(SessionParameter.BINDING_TYPE, BindingType.BROWSER.value());
parameters.put(SessionParameter.REPOSITORY_ID, "-default-");
try{
session = sf.createSession(parameters);
}catch(CmisUnauthorizedException cue){
session = null;
System.out.println("Wrong logging OR password !");
}
return session;
}
You are writing a runnable class which is not running the same process as Alfresco. In that sense, your class is running "remotely".
Because your class is running remotely to Alfresco, you are correct in using CMIS. But CMIS will only allow you to perform Create, Read, Update, and Delete (CRUD) functions against documents and folders in Alfresco. CMIS does not know how to create users or groups.
Your class will not be able to instantiate the AuthenticationService or PersonService. Those are part of the Alfresco Foundation API which only works when you are running in the same process as Alfresco, such as in an Action, a Behavior, or a Java-backed web script. In those cases, you will use Spring Dependency Injection to inject those services into your Java class. You would then put your class in a JAR that gets deployed into the Alfresco web application and loaded by the same classloader as Alfresco's.
If you want to create users remotely you should consider using the Alfresco REST API. Your runnable class can then use an HTTP client to invoke REST calls to create people and groups.
Thanks you for everything ! Thanks to you and researches I found out how to do it ! For the others who wonder how to do I'll post how I did and what site I used to understand it !
So you just need to manipulate JSON with Java because your alfresco people page (127.0.0.1:8080/alfresco/service/api/people) returns a JSON object, and you'll be able to create, delete, search... users! Thx again !
Sites :
https://api-explorer.alfresco.com/api-explorer/#/people
http://crunchify.com/json-manipulation-in-java-examples/
The code :
This is for creating an user :
public User createUser(String firstN, String lastN, String email, String pass, String authTicket) throws Exception{
try{
String url = "http://127.0.0.1:8080/alfresco/service/api/people?alf_ticket="+authTicket;
HttpClient httpclient = new HttpClient();
PostMethod mPost = new PostMethod(url);
//JSONObject obj = new JSONObject();
//JSONArray people = obj.getJSONArray("people");
JSONObject newUser = new JSONObject();
newUser.put("userName", firstN.toLowerCase().charAt(0)+lastN.toLowerCase());
newUser.put("enabled",true);
newUser.put("firstName",firstN);
newUser.put("lastName", lastN);
newUser.put("email", email);
newUser.put("quota",-1);
newUser.put("emailFreedDisable",false);
newUser.put("isDeleted",false);
newUser.put("isAdminAuthority",false);
newUser.put("password", pass);
//people.put(newUser);
//Response response = PostRequest(newUser.toString()));
StringRequestEntity requestEntity = new StringRequestEntity(
newUser.toString(),
"application/json",
"UTF-8");
mPost.setRequestEntity(requestEntity);
int statusCode2 = httpclient.executeMethod(mPost);
mPost.releaseConnection();
}catch(Exception e){
System.err.println("[ERROR] "+e);
}
return new User(firstN, lastN);
}
And if you want to get all the users you have on alfresco :
public ArrayList<User> getAllUsers(String authTicket)
{
ArrayList<User> allUsers = new ArrayList<>();
String lastName, firstName;
try{
String url = "http://127.0.0.1:8080/alfresco/service/api/people?alf_ticket="+authTicket;
HttpClient httpclient = new HttpClient();
GetMethod mPost = new GetMethod(url);
int statusCode1 = httpclient.executeMethod(mPost);
System.out.println("statusLine >>> "+statusCode1+"....."
+"\n status line \n"
+mPost.getStatusLine()+"\nbody \n"+mPost.getResponseBodyAsString());
JSONObject obj = new JSONObject(mPost.getResponseBodyAsString());
JSONArray people = obj.getJSONArray("people");
int n = people.length();
for(int i =0 ; i < n ; i++)
{
JSONObject peoples = people.getJSONObject(i);
User u = new User(peoples.getString("firstName"), peoples.getString("lastName"));
if (!allUsers.contains(u)){
allUsers.add(u);
}
}
}catch(Exception e){
System.err.println("[ERROR] "+e);
}
return(allUsers);
}
I upload an audio file to an audio & video bucket, called demo, using the AcrCloud RESTful services. I am getting a 500 Internal Server Error. This indicates that my signature is correct (I was getting a 422 when the signature was incorrect). The part that I suspect is incorrect is the construction of the multipart post request
My Code:
import com.xperiel.common.logging.Loggers;
import com.google.api.client.http.ByteArrayContent;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpContent;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpMediaType;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.MultipartContent;
import com.google.api.client.http.MultipartContent.Part;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.BaseEncoding;
import com.google.common.io.CharStreams;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class TestAcrCloudSignature {
private static final String ACCESS_KEY = "xxxx"; // confidential
private static final String SECRET_KEY = "yyyy"; // confidential
private static final String URL = "https://api.acrcloud.com/v1/audios";
private static HttpRequestFactory requestFactory = new NetHttpTransport().createRequestFactory();
private static final Logger logger = Loggers.getLogger();
public static void main(String [] args) {
String filePath = "/Users/serena/Desktop/ArcCloudMusic/Fernando.m4a";
String httpMethod = HttpMethod.POST.toString();
String httpUri = "/v1/audios";
String signatureVersion = "1";
long timestamp = System.currentTimeMillis();
String stringToSign = getStringToSign(httpMethod, httpUri, signatureVersion, timestamp);
String signature = getSignature(stringToSign);
logger.log(Level.INFO, "Timestamp:\t" + timestamp);
HttpResponse response = null;
try {
ImmutableMap<String, String> params = ImmutableMap.of(
"title", "fernando",
"audio_id", "1",
"bucket_name", "demo",
"data_type", "audio");
byte[] audio = getAudioFileTo(filePath);
String strResponse = sendMultiPartPostRequest(
"",
params,
ImmutableMap.of("audio-file", new Pair<>("Fernando.m4a", audio)),
signatureVersion,
signature,
timestamp);
logger.log(Level.INFO, "RESPONSE:" + strResponse);
} catch (Exception e) {
logger.log(Level.WARNING, "Response: " + response);
logger.log(Level.WARNING, "Exception: " + e.getMessage());
e.printStackTrace();
}
}
private static String getStringToSign(String method, String httpUri, String signatureVersion, long timestamp) {
String stringToSign = method+"\n"+httpUri+"\n"+ACCESS_KEY+"\n"+signatureVersion+"\n"+timestamp;
logger.log(Level.INFO, "String to Sign:\t" + stringToSign);
return stringToSign;
}
private static String getSignature(String stringToSign) {
String signature = BaseEncoding.base64().encode(hmacSha1(stringToSign));
logger.log(Level.INFO, "Signature:\t" + signature);
return signature;
}
private static byte[] hmacSha1(String toSign) {
try {
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec(SECRET_KEY.getBytes(), "HmacSHA1"));
return mac.doFinal(toSign.getBytes());
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException(e);
}
}
private enum HttpMethod {
GET, POST, PUT, DELETE,
}
private static byte[] getAudioFileTo(String filePath){
File file = new File(filePath);
byte[] buffer = null;
try {
InputStream fis = new FileInputStream(file);
buffer = new byte[(int) file.length()];
fis.read(buffer, 0, buffer.length);
fis.close();
} catch (IOException e) {
logger.log(Level.WARNING, "IOException: " + e.getMessage());
}
return buffer;
}
private static String sendMultiPartPostRequest(
String path,
ImmutableMap<String, String> parameters,
ImmutableMap<String, Pair<String, byte[]>> blobData,
String signatureVersion,
String signature,
long timestamp) {
try {
MultipartContent multipartContent = new MultipartContent();
multipartContent.setMediaType(new HttpMediaType("multipart/form-data"));
multipartContent.setBoundary("--------------------------0e94e468d6023641");
for (Entry<String, String> currentParameter : parameters.entrySet()) {
HttpHeaders headers = new HttpHeaders();
headers.clear();
headers.setAcceptEncoding(null);
headers.set("Content-Disposition", "form-data; name=\"" + currentParameter.getKey() + '\"');
HttpContent content = new ByteArrayContent(null, currentParameter.getValue().getBytes());
Part part = new Part(content);
part.setHeaders(headers);
multipartContent.addPart(part);
}
for (Entry<String, Pair<String, byte[]>> current : blobData.entrySet()) {
ByteArrayContent currentContent = new ByteArrayContent("application/octet-stream", current.getValue().second);
HttpHeaders headers = new HttpHeaders();
headers.clear();
headers.setAcceptEncoding(null);
headers.set("Content-Disposition", "form-data; name=\"" + current.getKey() + "\"; filename=\"" + current.getValue().first + '\"');
headers.setContentType("application/octet-stream");
multipartContent.addPart(new Part(headers, currentContent));
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
multipartContent.writeTo(out);
HttpResponse response = requestFactory
.buildPostRequest(new GenericUrl(URL + path), multipartContent)
.setHeaders(new HttpHeaders()
.set("access-key", ACCESS_KEY)
.set("signature-version", signatureVersion)
.set("signature", signature)
.set("timestamp", timestamp))
.execute();
String responseString = CharStreams.toString(new InputStreamReader(response.getContent()));
return responseString;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static class Pair<A, B> {
final A first;
final B second;
Pair(A first, B second) {
this.first = first;
this.second = second;
}
}
}
The error message I am getting from AcrCloud is:
500
{"name":"Internal Server Error","message":"There was an error at the server.","code":0,"status":500}
I am able to upload an audio file using this cUrl command:
Command: $ curl -H "access-key: xxxx" -H "signature-version: 1" -H
"timestamp: 1439958502089" -H "signature:
Nom6oajEzon260F2WzLpK3PE9e0=" -F "title=fernando" -F "audio_id=100" -F
"bucket_name=demo" -F "data_type=audio" -F
"audio_file=#/Users/serena/Desktop/ArcCloudMusic/Fernando.m4a"
https://api.acrcloud.com/v1/audios
Does anyone have any tips on how to debug this? Or has anyone had success using this service programmatically with Java? Or can someone show me how to print the contents of the HttpPOST request?
UPDATE I have also tried using their java example on GITHUB found here:
https://github.com/acrcloud/webapi_example/blob/master/RESTful%20service/UploadAudios.java
I get the same 500 error
UPDATE I no longer get the 500 error when I run their code. I fiddled with the apache jar versions and now I can successfully use the java code found on git hub. For record, The version that I used that work with their github code is apache-http-codec-1.10, apache-http-client-4.5, apache-http-core-4.4.1, apache-http-mime-4.5. When i used apache-http-core-4.5 it did not work.
UPDATE I have written a file that prints out the signatures generated by the java code on github reference above, and my own code. The signatures match so I am convinced that issue in the way I am constructing the multipart post request. I have also written the contents of both post requests to file and the headers contain different information in a few spots.
Thanks Serena for your patience, our team is doing a detailed analysis on the code and the apache jars now. Hopefully will have an update soon.
For now, if anyone who has the same problems, please use the following jars as mentioned in https://github.com/acrcloud/webapi_example/blob/master/RESTful%20service/UploadAudios.java
// import commons-codec-<version>.jar, download from http://commons.apache.org/proper/commons-codec/download_codec.cgi
import org.apache.commons.codec.binary.Base64;
// import HttpClient, download from http://hc.apache.org/downloads.cgi
/**
*
* commons-codec-1.1*.jar
* commons-logging-1.*.jar
* httpclient-4.*.jar
* httpcore-4.4.1.jar
* httpmime-4.*.jar
*
* */
Using the Rally Java Rest API, after I get the AttachmentContent object, how do I actually get the bytes which hold the content?
You may find the following example to be useful for what you are wanting to do. It's for a User Story rather than a Defect but the process would be identical for a Defect.
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.rallydev.rest.RallyRestApi;
import com.rallydev.rest.request.CreateRequest;
import com.rallydev.rest.request.DeleteRequest;
import com.rallydev.rest.request.GetRequest;
import com.rallydev.rest.request.QueryRequest;
import com.rallydev.rest.request.UpdateRequest;
import com.rallydev.rest.response.CreateResponse;
import com.rallydev.rest.response.DeleteResponse;
import com.rallydev.rest.response.GetResponse;
import com.rallydev.rest.response.QueryResponse;
import com.rallydev.rest.response.UpdateResponse;
import com.rallydev.rest.util.Fetch;
import com.rallydev.rest.util.QueryFilter;
import com.rallydev.rest.util.Ref;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.commons.codec.binary.Base64;
public class RestExample_DownloadAttachment {
public static void main(String[] args) throws URISyntaxException, IOException {
// Create and configure a new instance of RallyRestApi
// Connection parameters
String rallyURL = "https://rally1.rallydev.com";
String wsapiVersion = "1.43";
String applicationName = "RestExample_DownloadAttachment";
// Credentials
String userName = "user#company.com";
String userPassword = "topsecret";
RallyRestApi restApi = new RallyRestApi(
new URI(rallyURL),
userName,
userPassword
);
restApi.setWsapiVersion(wsapiVersion);
restApi.setApplicationName(applicationName);
// Workspace and Project Settings
String myWorkspace = "My Workspace";
String myProject = "My Project";
// FormattedID of Existing Test Case to Query
String existStoryFormattedID = "US43";
// Get reference to Workspace of interest
QueryRequest workspaceRequest = new QueryRequest("Workspace");
workspaceRequest.setFetch(new Fetch("Name", "Owner", "Projects"));
workspaceRequest.setQueryFilter(new QueryFilter("Name", "=", myWorkspace));
QueryResponse workspaceQueryResponse = restApi.query(workspaceRequest);
String workspaceRef = workspaceQueryResponse.getResults().get(0).getAsJsonObject().get("_ref").toString();
// Get reference to Project of interest
QueryRequest projectRequest = new QueryRequest("Project");
projectRequest.setFetch(new Fetch("Name", "Owner", "Projects"));
projectRequest.setQueryFilter(new QueryFilter("Name", "=", myProject));
QueryResponse projectQueryResponse = restApi.query(projectRequest);
String projectRef = projectQueryResponse.getResults().get(0).getAsJsonObject().get("_ref").toString();
// Query for existing User Story
System.out.println("Querying for User Story: " + existStoryFormattedID);
QueryRequest existUserStoryRequest = new QueryRequest("HierarchicalRequirement");
existUserStoryRequest.setFetch(new Fetch("FormattedID","Name","Attachments"));
existUserStoryRequest.setQueryFilter(new QueryFilter("FormattedID", "=", existStoryFormattedID));
QueryResponse userStoryQueryResponse = restApi.query(existUserStoryRequest);
JsonObject existUserStoryJsonObject = userStoryQueryResponse.getResults().get(0).getAsJsonObject();
String existUserStoryRef = userStoryQueryResponse.getResults().get(0).getAsJsonObject().get("_ref").toString();
JsonArray attachmentsJsonArray = existUserStoryJsonObject.getAsJsonArray("Attachments");
// Take first attachment
JsonObject attachmentObject = attachmentsJsonArray.get(0).getAsJsonObject();
String attachmentRef = attachmentObject.get("_ref").toString();
// Read attachment from Ref
System.out.println("Reading First Attachment: " + attachmentRef);
GetRequest attachmentRequest = new GetRequest(attachmentRef);
attachmentRequest.setFetch(new Fetch("Name","Content"));
GetResponse attachmentResponse = restApi.get(attachmentRequest);
// AttachmentContent object
JsonObject attachmentContentObject = attachmentResponse.getObject().get("Content").getAsJsonObject();
String attachmentContentRef = attachmentContentObject.get("_ref").toString();
// Read Content from Ref
System.out.println("Reading Attachment Content: " + attachmentRef);
GetRequest contentRequest = new GetRequest(attachmentContentRef);
contentRequest.setFetch(new Fetch("Content"));
GetResponse contentResponse = restApi.get(contentRequest);
// Read Content String of AttachmentContent
String attachmentContentBase64String = contentResponse.getObject().get("Content").getAsString();
// Grab attachment name
String attachmentName = attachmentResponse.getObject().get("Name").getAsString();
// Decode base64 string into bytes
byte[] imageBytes = Base64.decodeBase64(attachmentContentBase64String);
// Image output
String imageFilePath = "/Users/username/Desktop/";
String fullImageFile = imageFilePath + attachmentName;
// Write output file
System.out.println("Writing attachment to file: " + attachmentName);
try {
OutputStream imageOutputStream = new FileOutputStream(fullImageFile);
imageOutputStream.write(imageBytes);
imageOutputStream.flush();
imageOutputStream.close();
} catch (Exception e) {
System.out.println("Exception occurred while write image file ");
e.printStackTrace();
}
finally {
//Release all resources
restApi.close();
}
}
}
I am trying to learn more about MySQL and using Java (on Android) to access and retrieve information from a database on my WAMS server. The way my app is setup is that it has an initial login screen which also grabs the "uid" of the username that's logging in (from a different table) and stores it.
Upon login (which is functional - I setup a toast notification that displays the retrieved username and uid of the user logging in), it goes to a new screen (dashboard.xml) which has a TextView field setup to display the retrieved data (from table posted below) associated with the stored "uid". Here is the table I am trying to pull data from:
http://db.tt/4izVQuGB
Now, I have setup a PHP file that queries my db for rows that are associated with a specific "uid". I have tested this file using an HTML form.
$connect = mysql_connect($dbhost, $dbuser, $dbpass) or die("connection error");
mysql_select_db($dbdb)or die("database selection error");
//Retrieve the User ID
$uid = $_POST['uid'];
//Query
$query = mysql_query("SELECT * FROM node WHERE uid='$uid' AND type='goal'");
//store # of rows returned
$num_rows = mysql_num_rows($query);
if ($num_rows >= 1) {
while($results=mysql_fetch_assoc($query)) {
//Store the returned data into a variable
$output = $results;
//encode the returned data in JSON format
echo json_encode($output);
}
mysql_close();
}
The result I get by testing the PHP file using uid value of 1 is:
{"nid":"1","vid":"1","type":"goal","language":"","title":"test","uid":"1","status":"1","created":"1342894493","changed":"1342894493","comment":"2","promote":"1","moderate":"0","sticky":"1","tnid":"0","translate":"0"}
{"nid":"2","vid":"2","type":"goal","language":"","title":"test2","uid":"1","status":"1","created":"1342894529","changed":"1342894529","comment":"2","promote":"1","moderate":"0","sticky":"1","tnid":"0","translate":"0"}
{"nid":"5","vid":"5","type":"goal","language":"","title":"run","uid":"1","status":"1","created":"1343506987","changed":"1343506987","comment":"2","promote":"1","moderate":"0","sticky":"1","tnid":"0","translate":"0"}
{"nid":"9","vid":"9","type":"goal","language":"","title":"run to the
hills","uid":"1","status":"1","created":"1343604338","changed":"1343605100","comment":"2","promote":"0","moderate":"0","sticky":"0","tnid":"0","translate":"0"}
Now, I have written some android code which sets up httppost and is supposed to retrieve the "titles" in my database table. I know it is wrong (obviously since it doesn't work) but I am confused as to what to do next.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class Dashboard extends Activity implements OnClickListener {
// variable declarations
String uid = "1";
// create textview to display retrieved data
TextView display;
HttpClient httpclient;
HttpPost httppost;
HttpResponse httpresponse;
HttpEntity httpentity;
ArrayList<NameValuePair> resultArray;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dashboard);
display = (TextView) findViewById(R.id.test);
// initialize HttpClient
httpclient = new DefaultHttpClient();
// initialize HttpPost
httppost = new HttpPost("http://192.168.1.112/android/fetch.php");
try {
// Create new List
List<NameValuePair> resultList = new ArrayList<NameValuePair>();
resultList.add(new BasicNameValuePair("uid", uid));
httppost.setEntity(new UrlEncodedFormEntity(resultList));
httpresponse = httpclient.execute(httppost);
httpentity = httpresponse.getEntity();
InputStream instream = entity.getContent();
try {
// store incoming stream in an array
JSONArray jArray = new JSONArray(streamToString(instream));
JSONObject jData = null;
for (int i = 0; i < jArray.length(); i++) {
jData = jArray.getJSONObject(i);
String goals = jData.getString("title");
display.setText(goals);
}
//} catch (JSONException e) {
//Toast.makeText(this, "No entries found", Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(this, e.toString(), Toast.LENGTH_LONG)
.show();
}
} catch (Exception e) {
e.printStackTrace();
Notifications error = new Notifications();
error.userPassErrorDialog();
}
}
private static String streamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
public void onClick(View v) {
// TODO Auto-generated method stub
}
}
I get the following error when testing it in the Android emulator:
http://db.tt/2vg9MqYh
Any help or suggestions will be greatly appreciated.
In your Android app, you expect a JSONArray:
// store incoming stream in an array
JSONArray jArray = new JSONArray(streamToString(instream));
However, in your PHP file you only output multiple separate JSON objects instead of a real array. I think, you should collect all items from the database in an PHP array first and then encode and output it only once.
My PHP skills are a bit rusted, but I hope this one will work:
//store # of rows returned
$num_rows = mysql_num_rows($query);
if ($num_rows >= 1) {
$output = array();
while($results = mysql_fetch_assoc($query)) {
// append row to output
$output[] = results
}
mysql_close(); // shouldn't that be outside the if block?
//encode the returned data in JSON format
echo json_encode($output);
}
I would expect the output then to be like this (maybe without indentation):
[
{"nid":"1","vid":"1","type":"goal","language":"","title":"test","uid":"1","status":"1","created":"1342894493","changed":"1342894493","comment":"2","promote":"1","moderate":"0","sticky":"1","tnid":"0","translate":"0"},
{"nid":"2","vid":"2","type":"goal","language":"","title":"test2","uid":"1","status":"1","created":"1342894529","changed":"1342894529","comment":"2","promote":"1","moderate":"0","sticky":"1","tnid":"0","translate":"0"},
{"nid":"5","vid":"5","type":"goal","language":"","title":"run","uid":"1","status":"1","created":"1343506987","changed":"1343506987","comment":"2","promote":"1","moderate":"0","sticky":"1","tnid":"0","translate":"0"},
{"nid":"9","vid":"9","type":"goal","language":"","title":"run to the hills","uid":"1","status":"1","created":"1343604338","changed":"1343605100","comment":"2","promote":"0","moderate":"0","sticky":"0","tnid":"0","translate":"0"}
]
The problem lies in encoding and decoding of JSON. from your JSON response it looks like you are receiving JSON object from server also please try to validate you JSON response here. run your php file in browser, copy the entire response on the JSON validator and check the brackets that you are receiving the response in.
1. If your response starts with '[' it is and array and if it starts with '{' it is a JSON Object. while parsing JSON you have defined JSON array first but the server response is JSON object. While using JSON you have to be careful on server side for the format of response it will send and you have to be careful on the client side for the format of response you receive. I am posting example script for you.
-> Server side
if (mysql_num_rows($result)>0){
$response["data"] = array(); //this is an array
while($row= mysql_fetch_array($result))
{
$data = array(); //here I have created another temp array
$data["name"] = $row["name"];
$data["surname"] = $row["surname"];
array_push($response["data"], $data); //this makes an array of objects in the response
}}
}//endif
else{
echo "no input";
}}
mysql_close();
echo json_encode($response); //and finally I echo it as an JSON object
As this php script will return me one object of array of objects ( bit complex isn't it!!) below is the format of response
-> validated JSON response
{
"data": [
{
"name": "Setu",
"surname": "Desai",
}
]
}
and to decode this my client site script need to be the following
-> parsing JSON object
JSONObject snObject = new JSONObject(jsonString);
JSONArray snArray = snObject.getJSONArray("data");
for (int i = 0; i < snArray.length(); i++) {
JSONObject snObject2 = snArray.getJSONObject(i);
String surname = snObject2.getString("surname");
surnamearray.add(surname);
}
the simple way to understand is to validate you JSON response and identify the position of JSON array and objects and then start decoding.