I have the following code:
typealias MessagePredicate = (Message) -> Boolean
object EmailHelper {
private val session: Session by lazy {
val props = System.getProperties()
props["mail.imaps.usesocketchannels"] = "true"
props["mail.imap.usesocketchannels"] = "true"
Session.getInstance(props, null)
}
private val store = session.getStore("gimap") as GmailStore
private val idleManager = IdleManager(session, Executors.newSingleThreadExecutor())
private val folder: GmailFolder by lazy { store.getFolder("INBOX") as GmailFolder }
init {
store.connect("imap.gmail.com", "***#gmail.com", "***")
folder.open(Folder.READ_ONLY)
idleManager.watch(folder)
}
fun watchForMessage(condition: MessagePredicate): CompletableFuture<Message> {
val promise = CompletableFuture<Message>()
folder.addMessageCountListener(object : MessageCountAdapter() {
override fun messagesAdded(e: MessageCountEvent) {
super.messagesAdded(e)
e.messages.firstOrNull(condition)?.let {
folder.removeMessageCountListener(this)
promise.complete(it)
}
}
})
return promise
}
}
However when I run this code I'm getting the following exception:
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.muliyul.MainKt.main(Main.kt:28)
Caused by: javax.mail.MessagingException: Folder is not using SocketChannels
at com.sun.mail.imap.IdleManager.watch(IdleManager.java:205)
at com.muliyul.EmailHelper.<clinit>(EmailHelper.kt:40)
... 1 more
I am setting the property "mail.imaps.usesocketchannels" beforehand and I've also read this question yet I can't wrap my head around what's wrong with my code.
Can someone point me in the right direction?
Side note: the email provider is Gmail (obviously).
An hour after I posted this question (and 3 hours of researching) I finally found an answer.
You have to set the property mail.gimap.usesocketchannels to "true" (and not mail.imap.usesocketchannels or mail.imaps.usesocketchannels)
This is due to the fact that gimap is a different protocol than imap.
There goes 3 hours down the drain.
Related
I have a smart contract deployed. Whenever I try to perform a transaction, the transaction starts, but that's it. The transaction never actually takes place (or "doesn't get mined" might be the right word).
For reference, my smart contract function has takes one parameter and gives no output. just stores it. It's not that complex.
I do have reason to believe this has something to do with the transaction manager that I have set and how it doesn't provide enough nonce for any miner to take into consideration, since that was one of the answers on another question. However, they never said what the method was to fix it. I tried my best to fix it using a static gasProvider in hopes that it might be enough.
I have two pieces of code below:
VoteContractDelegate - This is used by rest of the application to make requests.
VoteContractAccessor - This extends the contract class and is used to return remotecall requests.
Note: I am using the web3j library.
VoteContractDelegate
private const val TAG = "VoteContractDelegate"
class VoteContractDelegate() {
//-----------------------------------------------------------------------------contract-elements
// TODO: get this from data store
private val USER_PRIVATE_KEY =
"66c53799ee0c63f2564305e738ea7479d7aee84aed3aac4c01e54a7acbcc4d92"
private val ROPSTEN_INFURA_URL = "https://ropsten.infura.io/v3/c358089e1aaa4746aa50e61d4ec41c5c"
private val credentials = Credentials.create(USER_PRIVATE_KEY)
private lateinit var web3j: Web3j//--------------------------------------------works-as-intended
private lateinit var contract: VoteContractAccessor
// TODO: set correct value
private val gasPrice: BigInteger = Convert.toWei("40", Convert.Unit.GWEI).toBigInteger()
//this gas limit value is from deployment and has to be constant
private val gasLimit = BigInteger.valueOf(4000000)
private val gasProvider: ContractGasProvider = StaticGasProvider(gasPrice, gasLimit)
init {
instantiateWeb3J()
web3j.ethGetTransactionCount(credentials.address, DefaultBlockParameterName.LATEST)
initializeContract()
}
private fun instantiateWeb3J() {
Log.d(
TAG, try {
web3j = Web3j.build(HttpService(ROPSTEN_INFURA_URL))
"Connection Successful"
} catch (e: Exception) {
e.printStackTrace()
"Connection Unsuccessful, error : ${e.message}"
}
)
}
private fun initializeContract() {
Log.d(
TAG, try {
contract = VoteContractAccessor(
web3j,
RawTransactionManager(web3j, credentials, ChainIdLong.ROPSTEN),
newGasProvider, credentials
)
"Contract Initialized Successfully"
} catch (e: Exception) {
"Contract Initialization Error"
}
)
}
// TODO: this is the problem function...
fun casteVote(party: PartyEnum): String {
return try {
Log.d(TAG,"started casteVote")
/**
* this starts but never completes. No errors outputted.
* If you watch closely, You'll see a '9' inside the get.
* that is the timeout duration. This function times out
* before being executed. It keeps waiting for whole 9
* minutes and then outputs a timeout error
*/
"cost = " + (
contract
.putVote(party)
.sendAsync()
.get(9, TimeUnit.MINUTES)
.gasUsed
.toString()
)
/**
* returns null as a result.
*/
} catch (e: Exception) {
e.printStackTrace()
e.message.toString()
}
}
}
VoteContractAccessor:
private const val TAG = "VoteContractAccessor"
private const val CONTRACT_BINARY =
"608060405234801561001057600080fd5b506000600281905560038190556004556103be8061002f6000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063449b6db21161005b578063449b6db2146100b8578063464d4a92146100db578063a483f4e1146100ee578063f5a31579146100f657600080fd5b8063068ea0eb146100825780630efcb43c1461008c57806342cff738146100a3575b600080fd5b61008a6100fe565b005b6004545b6040519081526020015b60405180910390f35b6100ab6101cb565b60405161009a9190610312565b3360009081526020819052604090205460ff16604051901515815260200161009a565b61008a6100e93660046102f9565b61022d565b600354610090565b600254610090565b3360009081526020819052604090205460ff16156101635760405162461bcd60e51b815260206004820152601b60248201527f596f75204861766520416c7265616479204265656e204164646564000000000060448201526064015b60405180910390fd5b336000818152602081905260408120805460ff191660019081179091558054808201825591527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601805473ffffffffffffffffffffffffffffffffffffffff19169091179055565b6060600180548060200260200160405190810160405280929190818152602001828054801561022357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610205575b5050505050905090565b60048110801561023d5750600081115b6102af5760405162461bcd60e51b815260206004820152603960248201527f74686520676976656e206e756d62657220697320696e76616c6964206173207460448201527f6865206e756d626572206973206f7574206f662072616e676500000000000000606482015260840161015a565b80600114156102d057600280549060006102c88361035f565b919050555050565b80600214156102e957600380549060006102c88361035f565b600480549060006102c88361035f565b60006020828403121561030b57600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156103535783516001600160a01b03168352928401929184019160010161032e565b50909695505050505050565b600060001982141561038157634e487b7160e01b600052601160045260246000fd5b506001019056fea264697066735822122036c7a6eb905bfb9bbcbf2436975878a32327f0fd4a8648f67281fd07be0ff4b064736f6c63430008070033"
private const val CONTRACT_ADDRESS = "0x84D46ba7aAac6221DF9038d3Ccf41F1cd46001aF"
class VoteContractAccessor(
private val web3obj: Web3j,
transactionManager: TransactionManager,
gasProvider: ContractGasProvider,
private val credentials: Credentials
) :
Contract(
CONTRACT_BINARY,
CONTRACT_ADDRESS,
web3obj,
transactionManager,
gasProvider
) {
//--------------------------------------------------------------------------------function-names
private val functionGetHasAlreadyVoted = "hasAlreadyVoted"
private val functionRegisterVote = "registerVote"
private val functionGetAddressValues = "getAddressValues"
private val functionGetPartyOneVotes = "getParty1Votes"
private val functionGetPartyTwoVotes = "getParty2Votes"
private val functionGetPartyThreeVotes = "getParty3Votes"
fun printBalance(): BigDecimal {
val balance =
Convert.fromWei(
web3obj.ethGetBalance(
credentials.address, DefaultBlockParameterName.LATEST
)
.send().balance.toString(),
Convert.Unit.ETHER
)
Log.d(TAG, "user balance = $balance")
return balance
}
fun putVote(party: PartyEnum): RemoteCall<TransactionReceipt> {
Log.d(TAG, "putVote\n\n\nstarted")
val function = Function(
functionRegisterVote,
listOf<Type<*>>(
Uint256(
when (party) {
PartyEnum.ONE -> 1
PartyEnum.TWO -> 2
PartyEnum.THREE -> 3
}
)
),
emptyList()
)
Log.d(TAG, "gas price = ${gasProvider.getGasPrice(functionRegisterVote)}")
return executeRemoteCallTransaction(function)
}
}
PartyEnum
enum class PartyEnum {
ONE, TWO, THREE
}
You can use the credentials provided if you want. It doesn't have any real ether anyway.
Instructions for if you want to look at the entire project...
if you want the entire project links, Github links -
Android studio project
Solidity project link
Once you open and run the android studio project, swipe right on the left side of the screen to open the drawer layout side menu (the navigation button for drawer layout doesn't work yet).
From there, open the contract interface option and then, you'll see the select party card on the top.
That is the function responsible for the voting transactions.
The back end for this card will be found in the directory named ui by the name ContractScreenFragment.
Then, somewhere at the top of that file you can find the onclick listener for the select party to vote card.
Here's what it would look like-
casteVoteButton.setOnClickListener {
viewModel.transactionCost.value = transactionInProgress
CoroutineScope(Dispatchers.IO).launch {
val cost = voteContractDelegate.casteVote(partyEnum)
Log.d(TAG, "transaction output:-\n$cost")
CoroutineScope(Dispatchers.Main).launch {
viewModel.transactionCost.value = cost
}
}
}
the rest of the functions have been mentioned above.
For a less complicated code, try checking the test button onclick listener at the end of the same file. That should be easier to understand.
That onclick listener is connected to the bottom card found inside the contract interface. you'll enter the gas price in Gwei in the edit text and then call the same function.
I have some code that works properly on spring boot prior to 2 and I find it hard to convert it to work with spring boot 2.
Can somebody assist?
public static MutablePropertySources buildPropertySources(String propertyFile, String profile)
{
try
{
Properties properties = new Properties();
YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
// load common properties
PropertySource<?> applicationYamlPropertySource = loader.load("properties", new ClassPathResource(propertyFile), null);
Map<String, Object> source = ((MapPropertySource) applicationYamlPropertySource).getSource();
properties.putAll(source);
// load profile properties
if (null != profile)
{
applicationYamlPropertySource = loader.load("properties", new ClassPathResource(propertyFile), profile);
if (null != applicationYamlPropertySource)
{
source = ((MapPropertySource) applicationYamlPropertySource).getSource();
properties.putAll(source);
}
}
propertySources = new MutablePropertySources();
propertySources.addLast(new PropertiesPropertySource("apis", properties));
}
catch (Exception e)
{
log.error("{} file cannot be found.", propertyFile);
return null;
}
}
public static <T> void handleConfigurationProperties(T bean, MutablePropertySources propertySources) throws BindException
{
ConfigurationProperties configurationProperties = bean.getClass().getAnnotation(ConfigurationProperties.class);
if (null != configurationProperties && null != propertySources)
{
String prefix = configurationProperties.prefix();
String value = configurationProperties.value();
if (null == value || value.isEmpty())
{
value = prefix;
}
PropertiesConfigurationFactory<?> configurationFactory = new PropertiesConfigurationFactory<>(bean);
configurationFactory.setPropertySources(propertySources);
configurationFactory.setTargetName(value);
configurationFactory.bindPropertiesToTarget();
}
}
PropertiesConfigurationFactory doesnt exist anymore and the YamlPropertySourceLoader load method no longer accepts 3 parameters.
(the response is not the same either, when I have tried invoking the new method the response objects were wrapped instead of giving me the direct strings/integers etc...)
The PropertiesConfigurationFactory should be replaced with Binder class.
Binder class
Sample code:-
ConfigurationPropertySource source = new MapConfigurationPropertySource(
loadProperties(resource));
Binder binder = new Binder(source);
return binder.bind("initializr", InitializrProperties.class).get();
We were also using PropertiesConfigurationFactory to bind a POJO to a
prefix of the Environment. In 2.0, a brand new Binder API was
introduced that is more flexible and easier to use. Our binding that
took 10 lines of code could be reduced to 3 simple lines.
YamlPropertySourceLoader:-
Yes, this class has been changed in version 2. It doesn't accept the third parameter profile anymore. The method signature has been changed to return List<PropertySource<?>> rather than PropertySource<?>. If you are expecting single source, please get the first occurrence from the list.
Load the resource into one or more property sources. Implementations
may either return a list containing a single source, or in the case of
a multi-document format such as yaml a source for each document in the
resource.
Since there is no accepted answer yet, i post my full solution, which builds upon the answer from #nationquest:
private ConfigClass loadConfiguration(String path){
MutablePropertySources sources = new MutablePropertySources();
Resource res = new FileSystemResource(path);
PropertiesFactoryBean propFactory = new PropertiesFactoryBean();
propFactory.setLocation(res);
propFactory.setSingleton(false);
// resolve potential references to local environment variables
Properties properties = null;
try {
properties = propFactory.getObject();
for(String p : properties.stringPropertyNames()){
properties.setProperty(p, env.resolvePlaceholders(properties.getProperty(p)));
}
} catch (IOException e) {
e.printStackTrace();
}
sources.addLast(new PropertiesPropertySource("prefix", properties));
ConfigurationPropertySource propertySource = new MapConfigurationPropertySource(properties);
return new Binder(propertySource).bind("prefix", ConfigClass.class).get();
}
The last three lines are the relevant part here.
dirty code but this is how i solved it
https://github.com/mamaorha/easy-wire/tree/master/src/main/java/co/il/nmh/easy/wire/core/utils/properties
I´m using graphDSL of akka stream to create a DSL for my test framework, but now that I´m looking how works I dont think it fit well.
My concern is that it seems like when I make an assert(false) in one of the flows instead of propagate the error in the test it´s getting stuck
I dont know if I´m doing something wrong
My DSL implementation looks like:
def given(message: String, musVersion: MUSVersion = ONE) = Source.single(new message(message, musVersion))
def When(sentence: String) = Flow[message].map(message => {
try {
HttpClient.request(message._1, message._2)
} catch {
case e: Exception => {
HttpResponse[String](e.getMessage, 500, Map())
}
}
})
def Then(sentence: String) = Sink.foreach[HttpResponse[String]](response => {
assert(false)
thenAction(sentence, response)
println(s"######## $x")
})
Like I said my test it get stuck instead mark the test as failure because of the assert.
Here my Test code:
class TestDSL extends MainDSL {
private def generateKey(): String = s"""${UUID.randomUUID().toString}"""
implicit val config = this.getRequestConfig("cassandra")
val message: String = Messages.message(path = "cassandra", key = "Cassandra " + generateKey())
info("This test has as requirement create and find an Entity using cassandra connector")
feature("First DSL") {
scenario(s"This is a prove of concept of the DSL") {
RunnableGraph.fromGraph(GraphDSL.create() { implicit builder =>
given(message) ~> When("I make a request") ~> Then("The return code='200'") ~> AndThen("The payload is not empty")
ClosedShape
}).run()
}
}
}
Any idea what´s wrong?.
Regards.
I need to perform unit testing on a kafka application avoiding third-party libraries.
My problem right now is that I would like to clear all the topics between tests but I don't know how.
This is my temporary solution: commit every message produced after each test and put all test consumers in the same consumer group.
override protected def afterEach():Unit={
val cleanerConsumer= newConsumer(Seq.empty)
val topics=cleanerConsumer.listTopics()
println("pulisco")
cleanerConsumer.subscribe(topics.keySet())
cleanerConsumer.poll(100)
cleanerConsumer.commitSync()
cleanerConsumer.close()
}
This doesn't work though and I don't know why.
For example, when I create a new consumer inside a test, messages contains the messages produced in the previous test.
val consumerProbe = newConsumer(SMSGatewayTopic)
val messages = consumerProbe.poll(1000)
How can I solve this?
You can also embed a Kafka/Zookeeper instances in your test sources, to have more controller over such isolated services.
trait Kafka { self: ZooKeeper =>
Kafka.start()
}
object Kafka {
import org.apache.hadoop.fs.FileUtil
import kafka.server.KafkaServer
#volatile private var started = false
lazy val logDir = java.nio.file.Files.createTempDirectory("kafka-log").toFile
lazy val kafkaServer: KafkaServer = {
val config = com.typesafe.config.ConfigFactory.
load(this.getClass.getClassLoader)
val (host, port) = {
val (h, p) = config.getString("kafka.servers").span(_ != ':')
h -> p.drop(1).toInt
}
val serverConf = new kafka.server.KafkaConfig({
val props = new java.util.Properties()
props.put("port", port.toString)
props.put("broker.id", port.toString)
props.put("log.dir", logDir.getAbsolutePath)
props.put(
"zookeeper.connect",
s"localhost:${config getInt "test.zookeeper.port"}"
)
props
})
new KafkaServer(serverConf)
}
def start(): Unit = if (!started) {
try {
kafkaServer.startup()
started = true
} catch {
case err: Throwable =>
println(s"fails to start Kafka: ${err.getMessage}")
throw err
}
}
def stop(): Unit = try {
if (started) kafkaServer.shutdown()
} finally {
FileUtil.fullyDelete(logDir)
}
}
trait ZooKeeper {
ZooKeeper.start()
}
object ZooKeeper {
import java.nio.file.Files
import java.net.InetSocketAddress
import org.apache.hadoop.fs.FileUtil
import org.apache.zookeeper.server.ZooKeeperServer
import org.apache.zookeeper.server.ServerCnxnFactory
#volatile private var started = false
lazy val logDir = Files.createTempDirectory("zk-log").toFile
lazy val snapshotDir = Files.createTempDirectory("zk-snapshots").toFile
lazy val (zkServer, zkFactory) = {
val srv = new ZooKeeperServer(
snapshotDir, logDir, 500
)
val config = com.typesafe.config.ConfigFactory.
load(this.getClass.getClassLoader)
val port = config.getInt("test.zookeeper.port")
srv -> ServerCnxnFactory.createFactory(
new InetSocketAddress("localhost", port), 1024
)
}
def start(): Unit = if (!zkServer.isRunning) {
try {
zkFactory.startup(zkServer)
started = true
while (!zkServer.isRunning) {
Thread.sleep(500)
}
} catch {
case err: Throwable =>
println(s"fails to start ZooKeeper: ${err.getMessage}")
throw err
}
}
def stop(): Unit = try {
if (started) zkFactory.shutdown()
} finally {
try { FileUtil.fullyDelete(logDir) } catch { case _: Throwable => () }
FileUtil.fullyDelete(snapshotDir)
}
}
The tests classes can extends Kafka with ZooKeeper to ensure this available.
If the test JVM is not forked, Tests.Cleanup in SBT testOptions in Test setting can be used to stop the embedded services after testing.
I would suggest, you simply recreate all topics before your tests. For example, this is the way kafka tests create/delete topics:
Kafka repository on GitHub
I have a flow described in this image:
if both event message fire, there's a control on the AND Converge Gateway to end the process or to log a string.
In case of only one of them fire, the process wait few seconds then check a variable into message data to decide if it must end or log instead.
Properties of the event message:
EventType a_fall_message
Name A message
Scope external
VariableName a_message
Code written into OR Gateway constraint to End:
return a_message.getConfidenceIndex() < 0.8;
Code written into OR Gateway constraint to Converge Gateway:
return a_message.getConfidenceIndex() >= 0.8;
The simple java main:
public static void main(String[] args) throws Exception {
KnowledgeBase knowledgeBase = readKnowledgeBase("messagetestevent.rf");
StatefulKnowledgeSession ksession = knowledgeBase.newStatefulKnowledgeSession();
Map<String, Object> parameterMap = new HashMap<String, Object>();
Integer i = 2;
parameterMap.put("groupId", i);
SimpleWorkItemHandler handler = new SimpleWorkItemHandler();
ksession.getWorkItemManager().registerWorkItemHandler("Log", handler);
ProcessInstance a = ksession.startProcess("com.droolstest.messagetestevent", parameterMap);
a.signalEvent("a_fall_message", new FallMessage(0.7));
a.signalEvent("b_fall_message", new FallMessage(0.7));
ksession.fireAllRules();
}
private static KnowledgeBase readKnowledgeBase(String name) throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource(name), ResourceType.DRF);
return kbuilder.newKnowledgeBase();
}
with the simple POJO:
public class FallMessage {
double confidenceIndex;
public FallMessage(double c) {
confidenceIndex = c;
}
public double getConfidenceIndex() {
return confidenceIndex;
}
public void setConfidenceIndex(double confidenceIndex) {
this.confidenceIndex = confidenceIndex;
}
}
So I need to access to the Message Event data variable a_message. When i play this simple project I see on the consolle this message:
Process Compilation error : org.drools.lang.descr.ProcessDescr#10e35d5
com/droolstest/Process_com_droolstest_0.java (8:357) : b_message cannot be resolved
com/droolstest/Process_com_droolstest_0.java (18:627) : b_message cannot be resolved
com/droolstest/Process_com_droolstest_0.java (28:897) : b_message cannot be resolved
com/droolstest/Process_com_droolstest_0.java (28:939) : a_message cannot be resolved
com/droolstest/Process_com_droolstest_0.java (38:1209) : b_message cannot be resolved
com/droolstest/Process_com_droolstest_0.java (38:1251) : a_message cannot be resolved
com/droolstest/Process_com_droolstest_0.java (48:1521) : a_message cannot be resolved
com/droolstest/Process_com_droolstest_0.java (58:1791) : a_message cannot be resolved
Exception in thread "main" java.lang.IllegalArgumentException: Could not parse knowledge.
at org.drools.builder.impl.KnowledgeBuilderImpl.newKnowledgeBase(KnowledgeBuilderImpl.java:58)
at com.droolstest.DroolsTest.readKnowledgeBase(DroolsTest.java:39)
at com.droolstest.DroolsTest.main(DroolsTest.java:17)
Have you got any suggestions?
Not sure what's happening exactly without seeing the actual bpmn2 xml, but it seems you're using variables called 'cnr_message' and 'emt_message' somewhere (in action scripts or conditions) but you haven't defined them as a process variable?
The compilation error is not directly complaining about a_message so if you defined that as a process variable, that seems to be working correctly at first glance.