I'm trying to use the AWS Java SDK to develop a ColdFusion application that uses the Amazon Transcribe service. Unfortunately my knowledge of Java is pitiful (to say nothing of the SDK itself) and I'm having a heck of a time getting anything to happen.
The code below is intended to start a transcription job. It doesn't throw an error, but it also doesn't start the job. I can't even tell if it's sending any information to AWS.
For all I know this code is completely off base, but right now my two biggest questions are:
Am I missing some obvious step to actually send the request to AWS?
How would I access any response I do get back from AWS? A dump of the invokeRequest variable appears to just be the request data.
Thanks in advance for any advice.
(FWIW: CF version is 2016, java version 1.8.0_171, and the AWS SDK is 1.11.331)
<cfscript>
/* Set up credentials */
awsCredentials = createObject('java','com.amazonaws.auth.BasicAWSCredentials').init('#variables.AWSAccessKeyID#', '#variables.AWSSecretKey#');
awsStaticCredentialsProvider = CreateObject('java','com.amazonaws.auth.AWSStaticCredentialsProvider').init(awsCredentials);
/* Create the Transcribe Service Object*/
serviceObject = CreateObject('java', 'com.amazonaws.services.transcribe.AmazonTranscribeAsyncClientBuilder').standard().withCredentials(variables.awsStaticCredentialsProvider).withRegion(#variables.awsRegion#).build();
/* Set up transcription job */
MediaFileUri = CreateObject('java','com.amazonaws.services.transcribe.model.Media').init();
MediaFileUri.setMediaFileUri('#variables.mediafilelocation#');
invokeRequest = CreateObject('java','com.amazonaws.services.transcribe.model.StartTranscriptionJobRequest').init();
invokeRequest.withLanguageCode('en-US');
invokeRequest.withMedia(MediaFileUri);
invokeRequest.withMediaFormat('wav');
invokeRequest.withTranscriptionJobName('#variables.jobname#');
/* Check results of request */
/* Shut down client*/
serviceObject.shutdown();
</cfscript>
Here is how I got this working. I'll start at the beginning, in case anyone reading this is as mystified as I was.
The first step is getting the AWS Java SDK. At some point I was under the impression that there was a separate SDK just for the Amazon Transcribe service, but that's not the case. Once you download the file, place the following jar files in the /{coldfusion}/lib/ folder (I'm not certain all of these are necessary, but this is what worked for me):
aws-java-sdk-xxxx.jar
httpclient-xxxx.jar
httpcore-xxxx.jar
jackson-annotations-xxxx.jar
jackson-core-xxxx.jar
jackson-databind-xxxx.jar
jackson-dataformat-cbor-xxxx.jar
joda-time-xxxx.jar
Restart the ColdFusion service.
The Transcribe service requires that the media file to be transcribed is in S3. I place my files in S3 using ColdFusion's native support into a bucket I've called "transcriptaudio", for example (note the colon separating the key ID from the secret):
<cffile
action = "copy"
source = "c:\temp\myfilename.wav"
destination = "s3://#variables.AWSAccessKeyID#:#variables.AWSSecretKey##transcriptaudio/">
The URL for the media will then be:
https://s3.{awsregion}.amazonaws.com/transcriptaudio/myfilename.wav
Then here is my code to start a transcription job:
<cfscript>
/* Set up credentials */
awsCredentials = CreateObject('java', 'com.amazonaws.auth.BasicAWSCredentials').init('#variables.AWSAccessKeyID#','#variables.AWSSecretKey#');
variables.awsStaticCredentialsProvider = CreateObject('java','com.amazonaws.auth.AWSStaticCredentialsProvider').init(awsCredentials);
/* Create the Transcribe Service Object*/
serviceObject = CreateObject('java', 'com.amazonaws.services.transcribe.AmazonTranscribeAsyncClientBuilder').standard().withCredentials(variables.awsStaticCredentialsProvider).withRegion(#variables.awsRegion#).build();
/* Set up transcription job */
MediaFileUri = CreateObject('java','com.amazonaws.services.transcribe.model.Media').init();
MediaFileUri.setMediaFileUri('#variables.mediafileurlstring#');
requestObject = CreateObject('java','com.amazonaws.services.transcribe.model.StartTranscriptionJobRequest').init();
requestObject.withLanguageCode('en-US');
requestObject.withMedia(MediaFileUri);
requestObject.withMediaFormat('wav');
requestObject.withTranscriptionJobName('#variables.jobName#');
/* Send the request */
sendRequest = serviceObject.startTranscriptionJob(requestObject);
/* Shut down client*/
serviceObject.shutdown();
</cfscript>
As Ageax noted in the comments, the transcription happens asynchronously, so I have a separate CF page to get the transcript after it completes. This code basically assumes the job is complete, but the transcriptionStatus variable will let me do that.
<cfscript>
/* Set up credentials */
awsCredentials = CreateObject('java','com.amazonaws.auth.BasicAWSCredentials').init('#variables.AWSAccessKeyID#','#variables.AWSSecretKey#');
variables.awsStaticCredentialsProvider = CreateObject('java','com.amazonaws.auth.AWSStaticCredentialsProvider').init(awsCredentials);
/* Create the Transcribe Service Object*/
serviceObject = CreateObject('java', 'com.amazonaws.services.transcribe.AmazonTranscribeAsyncClientBuilder').standard().withCredentials(variables.awsStaticCredentialsProvider).withRegion(#variables.awsRegion#).build();
/* Set up results object */
requestResultObject = CreateObject('java', 'com.amazonaws.services.transcribe.model.GetTranscriptionJobRequest').init();
requestResultObject.withTranscriptionJobName('#variables.jobName#');
/* Get the results */
requestResult = serviceObject.GetTranscriptionJob(requestResultObject);
/* parse result object into useful variables */
transcriptionStatus = requestResult.TranscriptionJob.TranscriptionJobStatus.toString();
transcriptURL = requestResult.TranscriptionJob.Transcript.TranscriptFileUri.toString();
</cfscript>
At this point I have the TranscriptURL, which when retrieved with cfhttp returns a vast amount of unnecessary information, at least for my use. Here is my code for getting the actual text of the transcript (the service returns the transcript in an array, so in case there's a possibility that there will be more than one transcript per job for some reason, I loop over the array) (and yes I switch to CF tags here because I'm just more comfortable working in tags):
<CFHTTP url="#variables.transcriptURL#" result="transcriptContentResponse">
<CFSET ResultsStruct = DeserializeJSON(variables.transcriptContentResponse.FileContent)>
<CFSET TranscriptsArray = ResultsStruct.Results.transcripts>
<CFLOOP Array = "#variables.TranscriptsArray#" index="ThisTranscript" >
<cfoutput>
#ThisTranscript['transcript']#
</cfoutput>
</CFLOOP>
Related
I am working on golang version of fabcar smart contract while seeking to implement a Java-SDK API which enrolls an admin, registers a user and performs query-update value operations based on https://github.com/hyperledger/fabric-samples/tree/master/fabcar/java
I have successfully set up a 3 org-9 peers blockchain network, installed, instantiated and invoked chaincode on peers.
However, as i am working on implementing the relative API, i am only able to successfully query blockchain database, while getting a "Could not meet endorsement policy for chaincode mycc"
Please find below screenshot of relative error
Endorsement policy is "OR ('Org1MSP.member','Org2MSP.member', 'Org3MSP.member')".
Should registered user somehow get an Org1/Org2/Org3.member attribute? Any leads would be appreciated!
Like #Ikar Pohorský said, for me this got resolved after I used correct method name. Also, ensure that you delete 'wallet' folder in order to regenerate the user if your HLF n/w was recreated.
#Test
public void testMyMethodToBeInvoked() throws Exception {
deleteDirectory(".\\wallet");
EnrollAdmin.main(null);
RegisterUser.main(null);
// Load a file system based wallet for managing identities.
final Path walletPath = Paths.get("wallet");
final Wallet wallet = Wallet.createFileSystemWallet(walletPath);
// load a CCP
final Path networkConfigPath = Paths
.get("C:\\sw\\hlf146-2\\fabric-samples\\first-network\\connection-org1.yaml");
final Gateway.Builder builder = Gateway.createBuilder();
builder.identity(wallet, "user1").networkConfig(networkConfigPath).discovery(true);
// create a gateway connection
try (Gateway gateway = builder.connect()) {
final Network network = gateway.getNetwork("mychannel");
final Contract contract = network.getContract("mycc");
String myJSONString="{\"a\":\"b\"}";
byte[] result;
// Following did NOT work. Control goes directly to 'invoke' when 'submitTransaction' is done directly. 'invoke' need not be mentioned here.
// result = contract.submitTransaction("invoke", myJSONString);
// Following DID work. In chaincode (my chain code was Java) I had a method named 'myMethodToBeInvoked'. The chain code was written similar to https://github.com/hyperledger/fabric-samples/blob/release-1.4/chaincode/chaincode_example02/java/src/main/java/org/hyperledger/fabric/example/SimpleChaincode.java
result = contract.submitTransaction("myMethodToBeInvoked", my);
System.out.println(new String(result));
}
}
EDIT: Also, please remember that if your chaincode throws errorResponse, even then we can have this endorsement fail issue. So, check if your chain code is working without any issues.
I am attempting to move an EC2 snapshot from one region to another.
When creating a basic Ec2 snapshot copy and copying it to a second Region I get the error protocol must not be null. It appears that the host is also null when you get to the point in the code that will require a host. From my understanding I do not need to provide the protocol (http/https) or the host details when copying a snapshot the is NOT encrypted. It appears that the AWS code should do this behind the scenes.
Off the top of my head this seems like an aws issue but there is not much feedback on the AWS SDK for Java V2 yet as I have checked here as well as github.
Program exception:
java.lang.NullPointerException: protocol must not be null
I have tried adding the destinationRegion to the builder but that also results in the same error.
Execution environment is Amazon Java 11.0.3
I have tried with software.amazon.awssdk versions 2.7.11 all the way through 2.7.29
Basic code snippet
String amazonAccessKeyId = "amazonAccessKeyId";
String amazonSecretKeyId = "amazonSecretKeyId";
String baseRegionName = "baseRegionName"; // Region.AP_NORTHEAST_1.id(); or where ever your snapshot is located
String remoteRegionName = "remoteRegionName "; // Region.AP_NORTHEAST_1.id(); or where ever your snapshot is located
String snapshotId = "snapshotId"; // You will need a snapshot to work with this code
// Setup AWS remote client with credentials
AwsCredentials credentials = AwsBasicCredentials.create(amazonAccessKeyId, amazonSecretKeyId);
Ec2Client amazonEc2RemoteRegionClient = Ec2Client.builder()
.region(Region.of(remoteRegionName))
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.build();
// Setup request
CopySnapshotRequest request = CopySnapshotRequest.builder()
.sourceRegion(Region.of(baseRegionName).id())
.sourceSnapshotId(snapshotId)
.description("Foo Bar Testing...")
.build();
// Invoke copy from remote region to pull in snapshot from source/default region
// This is the line in question
CopySnapshotResponse result = amazonEc2RemoteRegionClient.copySnapshot(request);
Stack trace follows
java.lang.NullPointerException: protocol must not be null.
at software.amazon.awssdk.utils.Validate.paramNotNull(Validate.java:117)
at software.amazon.awssdk.http.DefaultSdkHttpFullRequest.standardizeProtocol(DefaultSdkHttpFullRequest.java:63)
at software.amazon.awssdk.http.DefaultSdkHttpFullRequest.<init>(DefaultSdkHttpFullRequest.java:52)
at software.amazon.awssdk.http.DefaultSdkHttpFullRequest.<init>(DefaultSdkHttpFullRequest.java:41)
at software.amazon.awssdk.http.DefaultSdkHttpFullRequest$Builder.build(DefaultSdkHttpFullRequest.java:331)
at software.amazon.awssdk.http.DefaultSdkHttpFullRequest$Builder.build(DefaultSdkHttpFullRequest.java:170)
at software.amazon.awssdk.services.ec2.transform.internal.GeneratePreSignUrlInterceptor.modifyHttpRequest(GeneratePreSignUrlInterceptor.java:102)
at software.amazon.awssdk.core.interceptor.ExecutionInterceptorChain.modifyHttpRequestAndHttpContent(ExecutionInterceptorChain.java:99)
at software.amazon.awssdk.core.client.handler.BaseClientHandler.runModifyHttpRequestAndHttpContentInterceptors(BaseClientHandler.java:123)
at software.amazon.awssdk.core.client.handler.BaseClientHandler.finalizeSdkHttpFullRequest(BaseClientHandler.java:68)
at software.amazon.awssdk.core.client.handler.BaseSyncClientHandler.execute(BaseSyncClientHandler.java:106)
at software.amazon.awssdk.core.client.handler.BaseSyncClientHandler.execute(BaseSyncClientHandler.java:73)
at software.amazon.awssdk.core.client.handler.SdkSyncClientHandler.execute(SdkSyncClientHandler.java:44)
at software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler.execute(AwsSyncClientHandler.java:55)
at software.amazon.awssdk.services.ec2.DefaultEc2Client.copySnapshot(DefaultEc2Client.java:2808)
I expect the snapshot to be copied to the new region specified, without error, and not encrypted.
As a side note I have submitted this to Amazon through my support system and I am awaiting a response from them. I will update this post once they respond to my request.
copySnapshot
sdk error,builder with presignedUrl can skip it
I've integrated FreePBX with Vtiger (PBXManager),I've used this steps for integration https://wiki.vtiger.com/vtiger6/index.php/Asterisk_Integration
In my setup FreePBX and Vtiger both are on different server.
Calls are working fine but call status and other data is not updating in Vtiger. Even after call is hang-up its showing ringing in Call Status field and if I go to detail view its showing me recording URL as blank.
This is the log which I'm getting in nohup.webapp.log file
http://pastebin.com/m8ErDKt9
VtigerAsteriskConnector.properties
/*
* Copyright (C) www.vtiger.com. All rights reserved.
* #license Proprietary
*/
// Location where the application server will be running.
ServerIP = 127.0.0.1
ServerPort = 8383
// Call Recordings storage path
StorageDir = /VtigerAsteriskConnector/recordings
// Enable(true) or Disable(false) call recordings
Recording = true
// Location where the applications database files will be stored.
AsteriskAppDBPath = /VtigerAsteriskConnector/db
// Asterisk Server Details
AsteriskServerPublicIP = asterisk-server-public-ip
AsteriskServerIP = 127.0.0.1
AsteriskServerPort = 5038
AsteriskUsername = vtiger
AsteriskPassword = 5c11bea0b374299c2c70e09b4734a670
// Vtiger CRM URL
VtigerURL = http://vtigercrm.url.com
VtigerSecretKey = 167523039v54f1v677c2231
//Enable(true) or Disable(false) Asterisk Events and Database Logs in Connector
AsteriskLog = true
DatabaseLog = true
This seems related to asterisk-java library to me but I'm not sure,I've done same integration in one of my local VM and it works without any issue the only difference is in my local machine FreePBX and Vtiger both resides on same server.
I'll provide configuration files if anyone is needed.
Any suggestion and idea will be appreciated.
At current moment vtiger asterisk connector work only with asterisk 1.8
With any other version(1.4- or 11+) it not work correctly
I want to combine multiple GCS files into one big file. According to the docs there is a compose function, which looks like it does exactly what I need:
https://developers.google.com/storage/docs/json_api/v1/objects/compose
However, I can't find how to call that function from GAE using the Java client:
https://developers.google.com/appengine/docs/java/googlecloudstorageclient/
Is there a way to do this with that library?
Or should I mess around with reading the files one by one using channels?
Or should I call the low level JSON methods?
What's the best way?
Compose option available in the new Java client, I have tried using google-cloud-storage:1.63.0.
/** Example of composing two blobs. */
// [TARGET compose(ComposeRequest)]
// [VARIABLE "my_unique_bucket"]
// [VARIABLE "my_blob_name"]
// [VARIABLE "source_blob_1"]
// [VARIABLE "source_blob_2"]
public Blob composeBlobs(
String bucketName, String blobName, String sourceBlob1, String sourceBlob2) {
// [START composeBlobs]
BlobId blobId = BlobId.of(bucketName, blobName);
BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setContentType("text/plain").build();
ComposeRequest request =
ComposeRequest.newBuilder()
.setTarget(blobInfo)
.addSource(sourceBlob1)
.addSource(sourceBlob2)
.build();
Blob blob = storage.compose(request);
// [END composeBlobs]
return blob;
}
The compose operation does indeed do exactly what you want it to do. However, the compose operation isn't currently available for the GAE Google Cloud Storage client. You have a few alternatives.
You can use the non-GAE Google APIs client (link to the Java one). It invokes the lower level JSON API and supports compose(). The downside is that this client doesn't have any special AppEngine magic, so some little things will be different. For example, if you run it in the local development server, it will contact the real Google Cloud Storage. Also you'll need to configure it to authorize its requests, etc.
Another option would be to invoke the JSON or XML APIs directly.
Finally, if you only need to do this one time, you could simply use the command-line utility:
gsutil compose gs://bucket/source1 gs://bucket/source2 gs://bucket/output
I'm developing a mobile application with a mac, but it connects to a test server I'm running on linux and I'd like to enable APN on this server with a developer certificate, the question is, is it possible to install this certificate on my test server or I'll have to setup the test server on my linux machine?
To make this a little bit clearer:
My development machine: A Mac.
The test server: A linux machine running liferay 6.0.6
I want to install the development certificate on the test server so I can test push notifications.
Thanks a lot!
I know nothing about 'liferay' but this his how I setup a APN connection (on a Rails server) using the certificate. Note that you need to convert the certificate to a .pem file (using 'openssl pkcs12 -in myfile.p12 -out myfile.pem'):
##apn_cert = nil
APN_SSL_KEY_FILE = 'lib/SSLCert_Private_Key.pem'
APN_SSL_HOST = 'gateway.sandbox.push.apple.com'
# APN_SSL_HOST = 'gateway.push.apple.com'
APN_SSL_PORT = 2195
APN_SSL_PASSWORD = '<password>'
def configure_apn_cert
puts "APN Service: Configuring APN cert"
##apn_cert = File.read(File.join(RAILS_ROOT, APN_SSL_KEY_FILE))
##apn_context = OpenSSL::SSL::SSLContext.new
##apn_context.key = OpenSSL::PKey::RSA.new(##apn_cert, APN_SSL_PASSWORD)
##apn_context.cert = OpenSSL::X509::Certificate.new(##apn_cert)
end
def create_and_configure_apn_server
configure_apn_cert if not ##apn_cert
puts "APN Service: Configuring APN SOCKET and SSL connection"
#apn_socket = TCPSocket.new(APN_SSL_HOST, APN_SSL_PORT)
#apn_ssl = OpenSSL::SSL::SSLSocket.new(#apn_socket, ##apn_context)
#apn_ssl.sync = true
#apn_ssl.connect
end
def close_apn_server
#apn_ssl.close
#apn_socket.close
end
def package_build_for_apn( token, content )
"\0\0 #{token}\0#{content.length.chr}#{content}"
end
def package_send_to_apn( package )
puts "APN Service: Sending #{package}"
bytes_written = #apn_ssl.write( package )
if bytes_written != package.length then
puts "APN Service: SSL write failed"
package_to_apn_show_write( bytes_written, package)
end
end
def apn_deliver_payload( token, payload )
# Convert the device string back into a byte string
tokenBinary = Base64.decode64( token )
# Transform the payload into an APN byte string
apn_content = payload.to_hash.to_json
apn_content_len = apn_content.length
# Build the apn_package per APN specification
apn_package = "\0\0 #{tokenBinary}\0#{apn_content_len.chr}#{apn_content}"
# Actually send it.
package_send_to_apn( apn_package )
end
def package_to_apn_show_write( bytes, package)
puts "Wrote: #{bytes_written}/ Tried: #{package.length}"
puts "Package: '#{package}'"
end
def package_to_apn_debug( token, content, package )
puts "Token(#{token.length}): #{token}"
puts "Content(#{content.length}): #{content}"
puts "Package(#{package.length}): #{package}"
end
I'd like to answer my own question because it might help someone, first of all, I had a terrible confusion between the certificates I needed to generate and how to get the device token among other things.
These are the steps I went through to make this work:
Created an application ID.
Created a Certificate Signing Request using "Keychain access" and got the development certificate for push notifications which I installed using again Keychain access.
Exported the certificate as a .p12 file.
Used the notnoop java library (which is on the central maven repository) to send push notifications.
Here is a sample snippet that shows where the certificate fits in:
ApnsService service =
APNS.newService()
.withCert("/path/to/certificate.p12", "MyCertPassword")
.withSandboxDestination()
.build();
The second argument of the method is the password for the p12 file that keychain access makes you to set.
Finally to glue things, I used the [UIApplication sharedApplication] instance to register to receive push notifications and by implementing a method on the AppDelegate I get the token I needed which was in NSData format, so you need to converted into a hex string (there is sample code for that in many sites and questions on this site).
And that's it, that's the process.
Hope this helps!!