Skip to content

Commit 4655dcf

Browse files
authored
Merge pull request #178 from kemi04/grpc
[FABCJ-214] merged to release-2.2
2 parents 575b9c0 + 5610503 commit 4655dcf

File tree

25 files changed

+2232
-81
lines changed

25 files changed

+2232
-81
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
plugins {
2+
id 'com.github.johnrengelman.shadow' version '2.0.3'
3+
id 'java'
4+
}
5+
6+
version '0.0.1'
7+
8+
sourceCompatibility = 1.8
9+
10+
repositories {
11+
mavenLocal()
12+
mavenCentral()
13+
maven {
14+
url "https://www.jitpack.io"
15+
}
16+
maven {
17+
url "https://hyperledger.jfrog.io/hyperledger/fabric-maven"
18+
}
19+
20+
}
21+
22+
dependencies {
23+
compile group: 'org.hyperledger.fabric-chaincode-java', name: 'fabric-chaincode-shim', version: '2.2.+'
24+
compile group: 'org.json', name: 'json', version: '20180813'
25+
testImplementation 'org.junit.jupiter:junit-jupiter:5.4.2'
26+
testImplementation 'org.assertj:assertj-core:3.11.1'
27+
testImplementation 'org.mockito:mockito-core:2.+'
28+
}
29+
30+
shadowJar {
31+
baseName = 'chaincode'
32+
version = null
33+
classifier = null
34+
35+
manifest {
36+
attributes 'Main-Class': 'org.example.Application'
37+
}
38+
}
39+
40+
test {
41+
useJUnitPlatform()
42+
testLogging {
43+
events "passed", "skipped", "failed"
44+
}
45+
}
46+
47+
48+
tasks.withType(JavaCompile) {
49+
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" << "-parameters"
50+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*/
4+
5+
package org.example;
6+
7+
import java.io.IOException;
8+
import org.hyperledger.fabric.contract.ContractRouter;
9+
import org.hyperledger.fabric.shim.ChaincodeServer;
10+
import org.hyperledger.fabric.shim.ChaincodeServerProperties;
11+
import org.hyperledger.fabric.shim.NettyChaincodeServer;
12+
13+
public class Application {
14+
15+
private static final String CHAINCODE_SERVER_ADDRESS = "CHAINCODE_SERVER_ADDRESS";
16+
private static final String CORE_CHAINCODE_ID = "CORE_CHAINCODE_ID";
17+
18+
public static void main(String[] args) throws Exception {
19+
ChaincodeServerProperties chaincodeServerProperties = new ChaincodeServerProperties();
20+
21+
final String portChaincodeServer = System.getenv(CHAINCODE_SERVER_ADDRESS);
22+
if (portChaincodeServer == null || portChaincodeServer.isEmpty()) {
23+
throw new IOException("chaincode server port not defined in system env. for example 'CHAINCODE_SERVER_ADDRESS=0.0.0.0:9999");
24+
}
25+
final int port = Integer.parseInt(portChaincodeServer);
26+
chaincodeServerProperties.setPortChaincodeServer(port);
27+
28+
final String coreChaincodeIdName = System.getenv(CORE_CHAINCODE_ID);
29+
if (coreChaincodeIdName == null || coreChaincodeIdName.isEmpty()) {
30+
throw new IOException("core chaincode id not defined in system env. for example 'CORE_CHAINCODE_ID=externalcc:06d1d324e858751d6eb4211885e9fd9ff74b62cb4ffda2242277fac95d467033'");
31+
}
32+
33+
ContractRouter contractRouter = new ContractRouter(new String[] {"-i", coreChaincodeIdName});
34+
ChaincodeServer chaincodeServer = new NettyChaincodeServer(contractRouter, chaincodeServerProperties);
35+
36+
contractRouter.startRouterWithChaincodeServer(chaincodeServer);
37+
}
38+
39+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*/
4+
5+
package org.example.contract;
6+
7+
import org.hyperledger.fabric.contract.annotation.DataType;
8+
import org.hyperledger.fabric.contract.annotation.Property;
9+
import org.json.JSONObject;
10+
11+
@DataType()
12+
public class MyAsset {
13+
14+
@Property()
15+
private String value;
16+
17+
public MyAsset() {
18+
}
19+
20+
public String getValue() {
21+
return value;
22+
}
23+
24+
public void setValue(String value) {
25+
this.value = value;
26+
}
27+
28+
public String toJSONString() {
29+
return new JSONObject(this).toString();
30+
}
31+
32+
public static MyAsset fromJSONString(String json) {
33+
String value = new JSONObject(json).getString("value");
34+
MyAsset asset = new MyAsset();
35+
asset.setValue(value);
36+
return asset;
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*/
4+
package org.example.contract;
5+
6+
import static java.nio.charset.StandardCharsets.UTF_8;
7+
8+
import org.hyperledger.fabric.contract.Context;
9+
import org.hyperledger.fabric.contract.ContractInterface;
10+
import org.hyperledger.fabric.contract.annotation.Contract;
11+
import org.hyperledger.fabric.contract.annotation.Default;
12+
import org.hyperledger.fabric.contract.annotation.Transaction;
13+
14+
@Contract
15+
@Default
16+
public class MyAssetContract implements ContractInterface {
17+
18+
public MyAssetContract() {
19+
20+
}
21+
22+
@Transaction()
23+
public boolean myAssetExists(Context ctx, String myAssetId) {
24+
byte[] buffer = ctx.getStub().getState(myAssetId);
25+
return (buffer != null && buffer.length > 0);
26+
}
27+
28+
@Transaction()
29+
public void createMyAsset(Context ctx, String myAssetId, String value) {
30+
boolean exists = myAssetExists(ctx, myAssetId);
31+
if (exists) {
32+
throw new RuntimeException("The asset " + myAssetId + " already exists");
33+
}
34+
MyAsset asset = new MyAsset();
35+
asset.setValue(value);
36+
ctx.getStub().putState(myAssetId, asset.toJSONString().getBytes(UTF_8));
37+
}
38+
39+
@Transaction()
40+
public MyAsset readMyAsset(Context ctx, String myAssetId) {
41+
boolean exists = myAssetExists(ctx, myAssetId);
42+
if (!exists) {
43+
throw new RuntimeException("The asset " + myAssetId + " does not exist");
44+
}
45+
46+
MyAsset newAsset = MyAsset.fromJSONString(new String(ctx.getStub().getState(myAssetId), UTF_8));
47+
return newAsset;
48+
}
49+
50+
@Transaction()
51+
public void updateMyAsset(Context ctx, String myAssetId, String newValue) {
52+
boolean exists = myAssetExists(ctx, myAssetId);
53+
if (!exists) {
54+
throw new RuntimeException("The asset " + myAssetId + " does not exist");
55+
}
56+
MyAsset asset = new MyAsset();
57+
asset.setValue(newValue);
58+
59+
ctx.getStub().putState(myAssetId, asset.toJSONString().getBytes(UTF_8));
60+
}
61+
62+
@Transaction()
63+
public void deleteMyAsset(Context ctx, String myAssetId) {
64+
boolean exists = myAssetExists(ctx, myAssetId);
65+
if (!exists) {
66+
throw new RuntimeException("The asset " + myAssetId + " does not exist");
67+
}
68+
ctx.getStub().delState(myAssetId);
69+
}
70+
71+
}
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
* SPDX-License-Identifier: Apache License 2.0
3+
*/
4+
5+
package org.example;
6+
7+
import static java.nio.charset.StandardCharsets.UTF_8;
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
import static org.junit.jupiter.api.Assertions.assertFalse;
10+
import static org.junit.jupiter.api.Assertions.assertThrows;
11+
import static org.junit.jupiter.api.Assertions.assertTrue;
12+
import static org.mockito.Mockito.mock;
13+
import static org.mockito.Mockito.verify;
14+
import static org.mockito.Mockito.when;
15+
16+
import java.nio.charset.StandardCharsets;
17+
import org.example.contract.MyAsset;
18+
import org.example.contract.MyAssetContract;
19+
import org.hyperledger.fabric.contract.Context;
20+
import org.hyperledger.fabric.shim.ChaincodeServerProperties;
21+
import org.hyperledger.fabric.shim.ChaincodeStub;
22+
import org.junit.jupiter.api.Nested;
23+
import org.junit.jupiter.api.Test;
24+
25+
26+
public final class MyAssetContractTest {
27+
28+
@Nested
29+
class AssetExists {
30+
31+
@Test
32+
public void noProperAsset() {
33+
34+
MyAssetContract contract = new MyAssetContract();
35+
Context ctx = mock(Context.class);
36+
ChaincodeStub stub = mock(ChaincodeStub.class);
37+
when(ctx.getStub()).thenReturn(stub);
38+
39+
when(stub.getState("10001")).thenReturn(new byte[]{});
40+
boolean result = contract.myAssetExists(ctx, "10001");
41+
42+
assertFalse(result);
43+
}
44+
45+
@Test
46+
public void assetExists() {
47+
48+
MyAssetContract contract = new MyAssetContract();
49+
Context ctx = mock(Context.class);
50+
ChaincodeStub stub = mock(ChaincodeStub.class);
51+
when(ctx.getStub()).thenReturn(stub);
52+
53+
when(stub.getState("10001")).thenReturn(new byte[]{42});
54+
boolean result = contract.myAssetExists(ctx, "10001");
55+
56+
assertTrue(result);
57+
58+
}
59+
60+
@Test
61+
public void noKey() {
62+
MyAssetContract contract = new MyAssetContract();
63+
Context ctx = mock(Context.class);
64+
ChaincodeStub stub = mock(ChaincodeStub.class);
65+
when(ctx.getStub()).thenReturn(stub);
66+
67+
when(stub.getState("10002")).thenReturn(null);
68+
boolean result = contract.myAssetExists(ctx, "10002");
69+
70+
assertFalse(result);
71+
72+
}
73+
74+
}
75+
76+
@Nested
77+
class AssetCreates {
78+
79+
@Test
80+
public void newAssetCreate() {
81+
MyAssetContract contract = new MyAssetContract();
82+
Context ctx = mock(Context.class);
83+
ChaincodeStub stub = mock(ChaincodeStub.class);
84+
when(ctx.getStub()).thenReturn(stub);
85+
86+
String json = "{\"value\":\"TheAsset\"}";
87+
88+
contract.createMyAsset(ctx, "10001", "TheAsset");
89+
90+
verify(stub).putState("10001", json.getBytes(UTF_8));
91+
}
92+
93+
@Test
94+
public void alreadyExists() {
95+
MyAssetContract contract = new MyAssetContract();
96+
Context ctx = mock(Context.class);
97+
ChaincodeStub stub = mock(ChaincodeStub.class);
98+
when(ctx.getStub()).thenReturn(stub);
99+
100+
when(stub.getState("10002")).thenReturn(new byte[]{42});
101+
102+
Exception thrown = assertThrows(RuntimeException.class, () -> {
103+
contract.createMyAsset(ctx, "10002", "TheAsset");
104+
});
105+
106+
assertEquals(thrown.getMessage(), "The asset 10002 already exists");
107+
108+
}
109+
110+
}
111+
112+
@Test
113+
public void assetRead() {
114+
MyAssetContract contract = new MyAssetContract();
115+
Context ctx = mock(Context.class);
116+
ChaincodeStub stub = mock(ChaincodeStub.class);
117+
when(ctx.getStub()).thenReturn(stub);
118+
119+
MyAsset asset = new MyAsset();
120+
asset.setValue("Valuable");
121+
122+
String json = asset.toJSONString();
123+
when(stub.getState("10001")).thenReturn(json.getBytes(StandardCharsets.UTF_8));
124+
125+
MyAsset returnedAsset = contract.readMyAsset(ctx, "10001");
126+
assertEquals(returnedAsset.getValue(), asset.getValue());
127+
}
128+
129+
@Nested
130+
class AssetUpdates {
131+
132+
@Test
133+
public void updateExisting() {
134+
MyAssetContract contract = new MyAssetContract();
135+
Context ctx = mock(Context.class);
136+
ChaincodeStub stub = mock(ChaincodeStub.class);
137+
when(ctx.getStub()).thenReturn(stub);
138+
when(stub.getState("10001")).thenReturn(new byte[]{42});
139+
140+
contract.updateMyAsset(ctx, "10001", "updates");
141+
142+
String json = "{\"value\":\"updates\"}";
143+
verify(stub).putState("10001", json.getBytes(UTF_8));
144+
}
145+
146+
@Test
147+
public void updateMissing() {
148+
MyAssetContract contract = new MyAssetContract();
149+
Context ctx = mock(Context.class);
150+
ChaincodeStub stub = mock(ChaincodeStub.class);
151+
when(ctx.getStub()).thenReturn(stub);
152+
153+
when(stub.getState("10001")).thenReturn(null);
154+
155+
Exception thrown = assertThrows(RuntimeException.class, () -> {
156+
contract.updateMyAsset(ctx, "10001", "TheAsset");
157+
});
158+
159+
assertEquals(thrown.getMessage(), "The asset 10001 does not exist");
160+
}
161+
162+
}
163+
164+
@Test
165+
public void assetDelete() {
166+
MyAssetContract contract = new MyAssetContract();
167+
Context ctx = mock(Context.class);
168+
ChaincodeStub stub = mock(ChaincodeStub.class);
169+
when(ctx.getStub()).thenReturn(stub);
170+
when(stub.getState("10001")).thenReturn(null);
171+
172+
Exception thrown = assertThrows(RuntimeException.class, () -> {
173+
contract.deleteMyAsset(ctx, "10001");
174+
});
175+
176+
assertEquals(thrown.getMessage(), "The asset 10001 does not exist");
177+
}
178+
179+
@Test
180+
public void test() {
181+
ChaincodeServerProperties chaincodeServerProperties = new ChaincodeServerProperties();
182+
chaincodeServerProperties.setKeepAliveTimeMinutes(-10);
183+
184+
assertEquals(true, true);
185+
}
186+
187+
}

0 commit comments

Comments
 (0)