I have tried to upload a attachment in corda.
I have checked https://github.com/corda/corda/tree/release-M14. It is very complex and don't have a UI. When I tried to use some part of code it is showing full errors.
I have tried https://github.com/corda/blacklist . But here hash is finding in HTML page. Can I get a simple example to upload a document using UI and hash finding in kt file?
The blacklist sample here also has an example of uploading an attachment via RPC in Kotlin:
package net.corda.examples.attachments.client
import net.corda.client.rpc.CordaRPCClient
import net.corda.core.crypto.SecureHash
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.utilities.NetworkHostAndPort.Companion.parse
import net.corda.core.utilities.loggerFor
import net.corda.examples.attachments.ATTACHMENT_EXPECTED_CONTENTS
import net.corda.examples.attachments.ATTACHMENT_FILE_NAME
import net.corda.examples.attachments.BLACKLIST_JAR_PATH
import org.slf4j.Logger
import java.io.File
import java.util.jar.JarInputStream
/**
* Uploads the jar of blacklisted counterparties with whom agreements cannot be struck to the node.
*/
fun main(args: Array<String>) {
UploadBlacklistClient().main(args)
}
private class UploadBlacklistClient {
companion object {
val logger: Logger = loggerFor<UploadBlacklistClient>()
}
fun main(args: Array<String>) {
require(args.isNotEmpty()) { "Usage: uploadBlacklist <node address>" }
args.forEach { arg ->
val nodeAddress = parse(arg)
val rpcConnection = CordaRPCClient(nodeAddress).start("user1", "test")
val proxy = rpcConnection.proxy
val attachmentHash = uploadAttachment(proxy, BLACKLIST_JAR_PATH)
logger.info("Blacklist uploaded to node at $nodeAddress")
val attachmentJar = downloadAttachment(proxy, attachmentHash)
logger.info("Blacklist downloaded from node at $nodeAddress")
checkAttachment(attachmentJar, ATTACHMENT_FILE_NAME, ATTACHMENT_EXPECTED_CONTENTS)
logger.info("Attachment contents checked on node at $nodeAddress")
rpcConnection.notifyServerAndClose()
}
}
}
/**
* Uploads the attachment at [attachmentPath] to the node.
*/
private fun uploadAttachment(proxy: CordaRPCOps, attachmentPath: String): SecureHash {
val attachmentUploadInputStream = File(attachmentPath).inputStream()
return proxy.uploadAttachment(attachmentUploadInputStream)
}
/**
* Downloads the attachment with hash [attachmentHash] from the node.
*/
private fun downloadAttachment(proxy: CordaRPCOps, attachmentHash: SecureHash): JarInputStream {
val attachmentDownloadInputStream = proxy.openAttachment(attachmentHash)
return JarInputStream(attachmentDownloadInputStream)
}
/**
* Checks the [expectedFileName] and [expectedContents] of the downloaded [attachmentJar].
*/
private fun checkAttachment(attachmentJar: JarInputStream, expectedFileName: String, expectedContents: List<String>) {
var name = attachmentJar.nextEntry.name
while (name != expectedFileName) {
name = attachmentJar.nextEntry.name
}
val contents = attachmentJar.bufferedReader().readLines()
if (contents != expectedContents) {
throw IllegalArgumentException("Downloaded JAR did not have the expected contents.")
}
}
Related
I have a problem with this test code:
package mainPackage.tests
import com.google.firebase.firestore.FirebaseFirestore
import mainPackage.model.RepositoryMockup
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
class RepositoryTest {
#Test
fun testWriteNewUser() {
val repository = RepositoryMockup()
val email = "test.first#pwr.edu.pl"
val pass = "testpassword123"
val isATeacher = true
val task = repository.writeNewUser(pass, email, isATeacher)
task.addOnCompleteListener {
assertTrue(it.isSuccessful)
}
}
}
Here is an error:
And here is a class that I am testing:
package mainPackage.model
import com.google.firebase.firestore.FirebaseFirestore
import android.util.Log
import com.google.android.gms.tasks.Task
import com.google.firebase.firestore.FirebaseFirestoreException
import mainPackage.utils.Checks
const val TAG = "FIRESTORE"
class RepositoryMockup {
//--------------------------------
//Firebase functions
fun writeNewUser(pass: String, email: String, isATeacher: Boolean?) : Task<Void> {
val database = FirebaseFirestore.getInstance()
val myRef = database.collection("Users").document(email)
val newUser = hashMapOf(
"is_a_teacher" to isATeacher,
"pass" to pass
)
myRef.set(newUser)
.addOnSuccessListener { Log.d(TAG, "User successfully added") }
.addOnFailureListener { e -> Log.w(TAG, "Error writing user", e) }
return myRef.set(newUser)
}
}
It's only a small part of it. I hve tried a lot of things but they didn't help me.
I always got an error.
This class works perfect so the firebase was added correct.
Help me to fix this error.
I'm trying to expose an API for a CorDapp and the functions are not displaying. When looking at an example (https://github.com/roger3cev/obligation-cordapp), I receive the following page: https://imgur.com/a/ifOdrAd, however when I load my CorDapp, it says there are no installed Cordapps and /api on the localhost returns a 404. In the project, I feel the problem lies somewhere here: https://github.com/PronoyC/InsureFlight/tree/master/cordapp/src/main/kotlin/com/insureflight. I know this is very vague but I cannot find any errors that indicate a specific area. Any help would be appreciated.
InsureFlightApi.kt:
package com.insureflight
import net.corda.core.contracts.Amount
import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow
import com.insureflight.flows.IssuePolicy
import com.insureflight.flows.PayoutPolicy
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.contracts.getCashBalances
import net.corda.finance.flows.CashIssueFlow
import java.util.*
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces
import javax.ws.rs.QueryParam
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response
import javax.ws.rs.core.Response.Status.BAD_REQUEST
import javax.ws.rs.core.Response.Status.CREATED
#Path("insureflight")
class InsureFlightApi(val rpcOps: CordaRPCOps) {
private val myIdentity = rpcOps.nodeInfo().legalIdentities.first()
#GET
#Path("me")
#Produces(MediaType.APPLICATION_JSON)
fun me() = mapOf("me" to myIdentity)
#GET
#Path("peers")
#Produces(MediaType.APPLICATION_JSON)
fun peers() = mapOf("peers" to rpcOps.networkMapSnapshot()
.filter { nodeInfo -> nodeInfo.legalIdentities.first() != myIdentity }
.map { it.legalIdentities.first().name.organisation })
#GET
#Path("policies")
#Produces(MediaType.APPLICATION_JSON)
fun policies() = rpcOps.vaultQuery(Policy::class.java).states
#GET
#Path("cash")
#Produces(MediaType.APPLICATION_JSON)
fun cash() = rpcOps.vaultQuery(Cash.State::class.java).states
#GET
#Path("cash-balances")
#Produces(MediaType.APPLICATION_JSON)
fun getCashBalances() = rpcOps.getCashBalances()
#GET
#Path("self-issue-cash")
fun selfIssueCash(#QueryParam(value = "amount") amount: Int,
#QueryParam(value = "currency") currency: String): Response {
// 1. Prepare issue request.
val issueAmount = Amount(amount.toLong(), Currency.getInstance(currency))
val notary = rpcOps.notaryIdentities().firstOrNull() ?: throw IllegalStateException("Could not find a notary.")
val issueRef = OpaqueBytes.of(0)
val issueRequest = CashIssueFlow.IssueRequest(issueAmount, issueRef, notary)
// 2. Start flow and wait for response.
val (status, message) = try {
val flowHandle = rpcOps.startFlowDynamic(CashIssueFlow::class.java, issueRequest)
val result = flowHandle.use { it.returnValue.getOrThrow() }
CREATED to result.stx.tx.outputs.single().data
} catch (e: Exception) {
BAD_REQUEST to e.message
}
// 3. Return the response.
return Response.status(status).entity(message).build()
}
#GET
#Path("issue-policy")
fun issuePolicy(#QueryParam(value = "premium") premium: Int,
#QueryParam(value = "currency") currency: String,
#QueryParam(value = "client") client: String,
#QueryParam(value = "underwriter") underwriter: String,
#QueryParam(value = "flight") flight: String,
#QueryParam(value = "fStatus") fStatus: String): Response {
// 1. Create a premium object.
val issuePremium = Amount(premium.toLong() * 100, Currency.getInstance(currency))
// 2. Start the IssuePolicy flow. We block and wait for the flow to return.
val (status, message) = try {
val flowHandle = rpcOps.startFlowDynamic(
IssuePolicy.Initiator::class.java,
issuePremium,
client,
underwriter,
flight,
fStatus,
true
)
val result = flowHandle.use { it.returnValue.getOrThrow() }
CREATED to "Transaction id ${result.id} committed to ledger.\n${result.tx.outputs.single().data}"
} catch (e: Exception) {
BAD_REQUEST to e.message
}
// 3. Return the result.
return Response.status(status).entity(message).build()
}
#GET
#Path("payout-policy")
fun settlePolicy(#QueryParam(value = "id") id: String,
#QueryParam(value = "delayedMinutes") delayedMinutes: Int,
#QueryParam(value = "fStatus") fStatus: String): Response {
// 1. Get party objects for the counterparty.
val linearId = UniqueIdentifier.fromString(id)
// 2. Start the SettlePolicy flow. We block and wait for the flow to return.
val (status, message) = try {
val flowHandle = rpcOps.startFlowDynamic(
PayoutPolicy.Initiator::class.java,
linearId,
delayedMinutes,
fStatus,
true
)
flowHandle.use { flowHandle.returnValue.getOrThrow() }
CREATED to "Policy $linearId has been settled."
} catch (e: Exception) {
BAD_REQUEST to e.message
}
// 3. Return the result.
return Response.status(status).entity(message).build()
}
}
InsureFlightPlugin.kt (ObligationPlugin.kt is very similar to this):
package com.insureflight
import net.corda.core.messaging.CordaRPCOps
import net.corda.webserver.services.WebServerPluginRegistry
import java.util.function.Function
class InsureFlightPlugin : WebServerPluginRegistry {
override val webApis: List<Function<CordaRPCOps, out Any>> = listOf(Function(::InsureFlightApi))
override val staticServeDirs: Map<String, String> = mapOf(
"policy" to javaClass.classLoader.getResource("policyWeb").toExternalForm()
)
}
Kid101 is correct. You've to register the InsureFlightPlugin, like done here: obligation-cordapp/kotlin-source/src/main/resources/META-INF/services/net.corda.webserver.services.WebServerPluginRegistry
My Java migrations currently do not implement the MigrationChecksumProvider interface. I am wondering if they should.
I do not understand what role checksums play in Flyway. Would someone explain this to me, please? Moreover, if I implement MigrationChecksumProvider, how should a checksum be computed for a given migration?
Thank you.
Checksum are used for (accidental) change detection of migrations, which would invalidate the guarantee that the schema can be recreated exactly.
For Java migrations, the sky is the limit as to what you can do. It is therefore your call as to how you want to implement checksums to detect changes.
I think most of the time you want to calculate the checksum based upon the content of the class file in question. We are doing that like this....
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.CRC32;
import org.flywaydb.core.api.migration.jdbc.JdbcMigration;
import org.flywaydb.core.internal.util.FileCopyUtils;
import org.flywaydb.core.internal.util.logging.Log;
import org.flywaydb.core.internal.util.logging.LogFactory;
/**
* Utility class for checksum calculations.
*
*/
public final class Checksums {
private static final Log LOG = LogFactory.getLog(Checksums.class);
private Checksums() {
super(); // singleton
}
/**
* Calculates a checksum based on the given JdbcMigration. It builds the checksum from the byte content of the given
* migration class file using the same {#link CRC32} method as used by
* {#link org.flywaydb.core.internal.resolver.sql.SqlMigrationResolver}
*
* #param migration
* #return the checksum
*/
public static final Integer checksum(JdbcMigration migration) {
Integer checksum = null;
Class<?> migrationClass = migration.getClass();
String migrationClassFilePath = migrationClass.getName().replace(".", System.getProperty("file.separator")) + ".class";
InputStream inputStream = null;
try {
inputStream = ClassLoader.getSystemResourceAsStream(migrationClassFilePath);
byte[] classContent = FileCopyUtils.copyToByteArray(inputStream);
final CRC32 crc32 = new CRC32();
crc32.update(classContent);
checksum = (int) crc32.getValue();
} catch (IOException ioe) {
LOG.error("Problem calculating checksum for class " + migrationClass.getName(), ioe);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException ioe) {
LOG.error("Problem closing input stream to " + migrationClassFilePath, ioe);
}
}
}
return checksum;
}
}
Then you can create a base class that looks something like
public abstract class JdbcMigrationWithChecksum implements JdbcMigration, MigrationChecksumProvider {
#Override
public Integer getChecksum() {
return Checksums.checksum(this);
}
}
I am trying to use Rome for parsing some rss feeds. One of the rss feeds says
specifies 0.91 as the version and no custom xml namespace is defined but the entries still have a custom element in them. Can I use Rome to parse such custom tags without any defined namespace?
Thanks.
Yes. You need to write a custom parser to do it.
Let's say you want to handle the elements customString and customDate. Start by extending the Item class to store the custom elements.
package com.example;
import com.sun.syndication.feed.rss.Item;
import java.util.Date;
public class CustomItem extends Item {
private String _customString;
private Date _customDate;
public String getCustomString() {
return _customString;
}
public void setCustomString(String customString) {
_customString = customString;
}
public Date getCustomDate() {
return _customDate;
}
public void setCustomDate(Date customDate) {
_customDate = customDate;
}
}
Then write the parser. You also need to handle any standard elements you want to parse.
package com.example;
import com.example.CustomItem;
import com.sun.syndication.feed.rss.Item;
import com.sun.syndication.io.WireFeedParser;
import com.sun.syndication.io.impl.DateParser;
import com.sun.syndication.io.impl.RSS091UserlandParser;
import org.jdom.Element;
public class CustomParser extends RSS091UserlandParser implements WireFeedParser {
public CustomItem parseItem(Element rssRoot, Element eItem) {
CustomItem customItem = new CustomItem();
// Standard elements
Item standardItem = super.parseItem(rssRoot, eItem);
customItem.setTitle(standardItem.getTitle());
customItem.setDescription(standardItem.getDescription());
// Non-standard elements
Element e = eItem.getChild("customString", getRSSNamespace());
if (e != null) {
customItem.setCustomString(e.getText());
}
e = eItem.getChild("customDate", getRSSNamespace());
if (e != null) {
customItem.setCustomDate(DateParser.parseDate(e.getText()));
}
return customItem;
}
}
Finally you need to define your parser in a rome.properties file along with parsers for any other type of feed you want to handle.
# Feed Parser implementation classes
#
WireFeedParser.classes=com.example.CustomParser
You need to write a custom converter to get the data.
part of code same to above.
Start by extending the Item class to store the custom elements.
package com.example;
import com.sun.syndication.feed.rss.Item;
import java.util.Date;
public class CustomItem extends Item {
private String _customString;
private Date _customDate;
public String getCustomString() {
return _customString;
}
public void setCustomString(String customString) {
_customString = customString;
}
public Date getCustomDate() {
return _customDate;
}
public void setCustomDate(Date customDate) {
_customDate = customDate;
}
}
Then write the parser. You also need to handle any standard elements you want to parse.
package com.example;
import com.example.CustomItem;
import com.sun.syndication.feed.rss.Item;
import com.sun.syndication.io.WireFeedParser;
import com.sun.syndication.io.impl.DateParser;
import com.sun.syndication.io.impl.RSS091UserlandParser;
import org.jdom.Element;
public class CustomParser extends RSS091UserlandParser implements WireFeedParser {
public CustomItem parseItem(Element rssRoot, Element eItem) {
CustomItem customItem = new CustomItem();
// Standard elements
Item standardItem = super.parseItem(rssRoot, eItem);
customItem.setTitle(standardItem.getTitle());
customItem.setDescription(standardItem.getDescription());
// Non-standard elements
Element e = eItem.getChild("customString", getRSSNamespace());
if (e != null) {
customItem.setCustomString(e.getText());
}
e = eItem.getChild("customDate", getRSSNamespace());
if (e != null) {
customItem.setCustomDate(DateParser.parseDate(e.getText()));
}
return customItem;
}
}
Then write the converter.
public class CustomConverter extends ConverterForRSS20 {
protected SyndEntry createSyndEntry(Item item) {
List<HashMap<String,String>> temp = new ArrayList<HashMap<String,String>>();
SyndEntry syndEntry = super.createSyndEntry(item);
customItem customItem = (customItem)item;
List<String> customList = new ArrayList<String>();
customList.add( customItem.getCustomString() );
//set to empty attribute ex foreignmarkup
syndEntry.setForeignMarkup( customList );
return syndEntry;
}
}
Finally you need to define your parser in a rome.properties file along with parsers for any other type of feed you want to handle.
# Feed Parser implementation classes
#
WireFeedParser.classes=com.example.CustomParser
# Feed Converter implementation classes
#
Converter.classes=com.example.CustomConverter
Then you can get value.
SyndFeed feed = input.build(new XmlReader(feedUrl));
List<SyndEntryImpl> entrys = feed.getEntries();
for(SyndEntryImpl entry:entrys ){
System.out.println( entry.getForeignMarkup() );
}
I have been trying to play a video that was converted using http://www.mirovideoconverter.com/ to mp4 file , it is woking fine on the simulator but on the ipad i don't see the video.
How can I fix??
attaching Video code :
package com.view.generic
{
import com.constants.Dimentions;
import com.view.AbstractScreen;
import com.view.IScreen;
import com.view.gui.Btn;
import flash.errors.IOError;
import flash.events.IOErrorEvent;
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import org.osflash.signals.natives.NativeSignal;
public class VideoMode extends AbstractScreen implements IScreen
{
private var _player:Video;
private var _stream:NetStream;
public function VideoMode()
{
}
override public function start():void{
super.start();
var conn:NetConnection = new NetConnection();
conn.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler)
conn.addEventListener(IOErrorEvent.NETWORK_ERROR, netStatusError)
conn.connect(null);
layoutPlayer();
layoutMenu();
}
override public function stop():void{
_stream.pause();
}
private function layoutMenu():void{
var playBtn:Btn = new Btn("video_play_button.png");
addChild(playBtn);
playBtn.x = (Dimentions.HEIGHT -playBtn.width)/2;
playBtn.y = _player.y+_player.height+20;
var clickSignal:NativeSignal = new NativeSignal(playBtn,MouseEvent.CLICK);
clickSignal.add(play);
var fullScrBtn:Btn = new Btn("full_screen.png");
addChild(fullScrBtn);
fullScrBtn.x = _player.width -fullScrBtn.width+_player.x;;
fullScrBtn.y = _player.y+_player.height+20;
var fullScrSignal:NativeSignal = new NativeSignal(fullScrBtn,MouseEvent.CLICK);
fullScrSignal.add(goFullScreen);
}
private function layoutPlayer():void{
_player.width = 400;
_player.height = 300;
_player.x = (Dimentions.HEIGHT -_player.width)/2;
_player.y = 200;
_stream.play("../../../assets/drum_ny.flv");
_stream.pause();
}
private function goFullScreen(e:MouseEvent):void{
if(_player.x == 0){
layoutPlayer()
}else{
_player.x = 0;
_player.y = 0;
_player.width = stage.fullScreenWidth;
_player.height = stage.fullScreenHeight;
}
}
private function play(e:MouseEvent):void{
_stream.resume()
}
private function netStatusHandler(e:NetStatusEvent):void{
if(e.info.code=="NetConnection.Connect.Success"){
_stream = new NetStream(NetConnection(e.target));
_stream.client = this;
_player = new Video();
addChild(_player);
_player.attachNetStream(_stream)
}
}
private function netStatusError(e:IOError):void{
trace(e)
}
override public function destroy():void{
}
public function onMetaData(info:Object):void {
}
}
}
Thank you!
This is likely your problem :
_stream.play("../../../assets/drum_ny.flv");
That file doesn't exist once you compile your app into a .ipa file. Try changing that to a web address of somewhere you can upload it to and if it works, then that's your prob.
The issue was resolved by replacing the FLV file, however I am still not sure why one flv file works and the other does not.
If you encounter such a problem (video works on simulator but not on device) your first bet should be replacing the video source.