I know how to define an external action that is atomic (has to arguments) such as "sitDown" and then manually code it in the Environment Java file within the execute action method.
However, if I define an external action, is there a way for it to accept arguments?
Let us say I want to define an action that can be invoked in agent code this way:
destroy(4, 7);
In my environment class, how would I retrieve those values within the execute action method?
Yes, you can send arguments to the environment as well as get feedbacks.
For example, in an application, a method that is changing a LED of a robot could be like this (this belongs to a class that extends Artifact - CArtAgO):
#OPERATION
void changeLedPin(String newState) throws Exception {
try {
/** put gpio HIGH */
if (newState.equals("high")) {
logger.info("Changing pin to HIGH!");
ledPin.high();
}
/** put gpio LOW */
if (newState.equals("low")) {
logger.info("Changing pin to LOW!");
ledPin.low();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Jason's agent code to invoke this external action could be like this:
!start.
+!start <-
changeLedPin(low).
For feedbacks you can use OpFeedbackParam sending in Jason code a variable to unify. The artifact method is something like this:
#OPERATION
void inc(OpFeedbackParam<String> value) {
/* some code */
}
Sources: https://github.com/cleberjamaral/goldminers/blob/master/src/env/mining/Raspi.java
https://github.com/cleberjamaral/camel-artifact/blob/master/camelJaCaMoRobot/src/env/artifacts/Counter.java
If not using Cartago environment, but the Jason Environment, you can get the values of the arguments using the Structure class API. For example:
class ... extends Environment {
...
public boolean executeAction(String ag, Structure action) {
NumberTerm arg0 = (NumberTerm)action.getTerm(0);
int vl = (int)arg0.solve();
}
...
The Jason API is available here.
Related
1、Can I use bulkhead pattern in feignClient?
2、I have some confusion about hystrix.
For example,if I only have three feign clients "a","b","c"。The "a" calls "b" and "c".
I know I can easily use circuit breaker with fallback parameter and some Configuration like this:
#FeignClient(name = "b", fallback = bFallback.class)
protected interface HystrixClient {
//some methods
}
#FeignClient(name = "c", fallback = cFallback.class)
protected interface HystrixClient {
//some methods
}
In another way,I could use #HystrixCommand to wrap my remote call with some Configuration like this:
#HystrixCommand(fallbackMethod="getFallback")
public Object get(#PathVariable("id") long id) {
//...
}
In addition I can configure some parameter in #HystrixCommand or application.yml,and I also can add threadPoolKey in in #HystrixCommand
Q1:I have learn that Hystrix wrapped remote call to achieve purpose,I can understand on the latter way,but the former way likes wrapping callee?
I found in document that:
Feign will wrap all methods with a circuit break
Is this mean FeignClient seems adding #Hystrixcommand on every method in interface in essence?
Q2:If the Feign client "b" have three remote call,how can I let them run in bulkhead to avoid one method consuming all thread? to Combine the feignClient and #HystrixCommand? will them conflict?
Because I do not found the parameter likes threadPoolKey in feignClient. Auto bulkhead?
Q3:If my hystrix configuration is in application.yml ,the feignClient pattern and #HytirxCommand pattern whether have the same configuration pattern? like this:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds:1000
circuitBreaker:
requestVolumeThreshold:10
...
...
but what's the follow Timeout?
feign:
client:
config:
feignName:
connectTimeout: 5000
readTimeout: 5000
1、Can I use bulkhead pattern in feignClient?
Java doc of setterFactory() method of HystrixFeign class says:
/**
* Allows you to override hystrix properties such as thread pools and command keys.
*/
public Builder setterFactory(SetterFactory setterFactory) {
this.setterFactory = setterFactory;
return this;
}
https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html says:
Spring Cloud Netflix does not provide the following beans by default for feign, but still looks up beans of these types from the application context to create the feign client:
• Logger.Level
• Retryer
• ErrorDecoder
• Request.Options
• Collection
• SetterFactory
So we should create setterFactory and specifying thread pool there. You can create a Bean like this:
#Bean
public SetterFactory feignHystrixSetterFactory() {
return (target, method) -> {
String groupKey = target.name();
String commandKey = Feign.configKey(target.type(), method);
return HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey( target.type().getSimpleName() ));
};
}
but what's the follow Timeout?
Feign client timeout is similar to ribbon timeout and specifies the properties of httpconnectin but you can define different timeouts for different feignclient.
feign.client.config.bar.readTimeout //this configuration will apply to bar client
feign.client.config.default.readTimeout // this configuration will apply to all feign
How did I found that? if you debug your application and put breakpoints on the following code of RetryableFeignLoadBalancer class:
final Request.Options options;
if (configOverride != null) {
RibbonProperties ribbon = RibbonProperties.from(configOverride);
options = new Request.Options(ribbon.connectTimeout(this.connectTimeout),
ribbon.readTimeout(this.readTimeout));
}
else {
options = new Request.Options(this.connectTimeout, this.readTimeout);
}
you will see these value will be used as properties of HTTPConection.pls have a look at feign.Client class.
connection.setConnectTimeout(options.connectTimeoutMillis());
connection.setReadTimeout(options.readTimeoutMillis());
I'm not able to figure out how to run a whole scenario before an other scenario, so that my test are not dependant on eachother.
I have this imaginary scenarios.
Scenario A
Given I have something
When I sumbit some data
I should see it on my webpage
Scenario B
Given SCENARIO A
When I delete the data
I should not see it on my webpage
When I run this scenario case, the software does not recognize Scenario A in scenario B, and ask me to create the step, like this...
You can implement missing steps with the snippets below:
#Given("^Registrere formue og inntekt$")
public void registrere_formue_og_inntekt() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
You could either:
Use a Background to group all the steps that need to be executed before the different scenarii:
Background:
Given I have something
When I submit some data
Then I should see it on my webpage
Scenario: B
When I delete the data
Then I should not see it on my webpage
Group them as part of a step definition:
#Given("^Scenario A")
public void scenario_A() {
I_have_something();
I_submit_some_data();
I_should_see_it_on_my_page();
}
which you can then use like this:
Given Scenario A
When I delete the data
Then I should not see it on my webpage
Using this technique, you usually observe that some actions are constantly reused, and you may want to factor them out so that they can be reused across different step definitions; at that point, the Page Object pattern comes very handy.
Cucumber scenarios are supposed to be independent. A lot of work is done assuming and ensuring that independence. Trying to go against will be an obstacle course.
Having said that, you could create your custom implementation of the Cucumber JUnit runner. Having this custom implementation, and by looking at the source of the original runner, you can expose / wrap / change the internals to allow what you want. For example with the following runner:
public class MyCucumber extends Cucumber {
private static Runtime runtime;
private static JUnitReporter reporter;
private static List<CucumberFeature> features;
public MyCucumber(Class<?> clazz) throws InitializationError, IOException {
super(clazz);
}
#Override
#SuppressWarnings("static-access")
protected Runtime createRuntime(ResourceLoader resourceLoader,
ClassLoader classLoader, RuntimeOptions runtimeOptions)
throws InitializationError, IOException {
this.runtime = super.createRuntime(resourceLoader, classLoader, runtimeOptions);
this.reporter = new JUnitReporter(runtimeOptions.reporter(classLoader), runtimeOptions.formatter(classLoader), runtimeOptions.isStrict());
this.features = runtimeOptions.cucumberFeatures(resourceLoader);
return this.runtime;
}
public static void runScenario(String name) throws Exception {
new ExecutionUnitRunner(runtime, getScenario(name), reporter).run(new RunNotifier());
}
private static CucumberScenario getScenario(String name) {
for (CucumberFeature feature : features) {
for (CucumberTagStatement element : feature.getFeatureElements()) {
if (! (element instanceof CucumberScenario)) {
continue;
}
CucumberScenario scenario = (CucumberScenario) element;
if (! name.equals(scenario.getGherkinModel().getName())) {
continue;
}
return scenario;
}
}
return null;
}
}
You can setup your test suite with:
#RunWith(MyCucumber.class)
public class MyTest {
}
And create a step definition like:
#Given("^I first run scenario (.*)$")
public void i_first_run_scenario(String name) throws Throwable {
MyCucumber.runScenario(name);
}
It is a fragile customization (can break easily with new versions of cucumber-junit) but it should work.
I'm trying to put together my first Akka/Camel application from "scratch" (read, "noob") using the following lib versions:
akka-camel: 2.2.0-RC1
According to all of the documentation I can find (Akka docs, user groups, etc.) all I have to do to consume from a file-based queue is set up my system this way:
Main class:
actorSystem = ActorSystem.create("my-system");
Props props = new Props(Supervisor.class);
ActorRef supervisor = actorSystem.actorOf(props, "supervisor");
Camel camel = CamelExtension.get(actorSystem);
CamelContext camelContext = camel.context();
camelContext.start();
Supervisor class:
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.camel.javaapi.UntypedConsumerActor;
import org.apache.camel.Message;
/**
* Manages creation and supervision of UploadBatchWorkers.
*/
public class Supervisor extends UntypedConsumerActor {
#Override
public String getEndpointUri() {
return "file:///Users/myhome/queue";
}
#Override
public void preStart() {
String test = "test";
}
#Override
public void onReceive(Object message) {
if (message instanceof CamelMessage) {
// do something
}
}
My problem is that even though I know the supervisor object is being created and breaks during debugging on the preStart() method's "test" line (not to mention that if I explicitly "tell" it something it processes fine), it does not consume from the defined endpoint, even though I have another application producing messages to the same endpoint.
Any idea what I'm doing wrong?
Ok, the problem was my own fault and is clearly visible in the example code if you look at the Consumer trait from which the UntypedConsumerActor inherits.
This method:
#Override
public void preStart() {
String test = "test";
}
overrides its parent's preStart() method, right? Well, that parent method is actually the one that registers the consumer with the on-the-fly created endpoint, so while you can override it, you must call super() or it will not work.
Hope this is useful to someone down the road!
Try changing your instanceof inside of onReceive to this:
if (message instanceof CamelMessage){
//do processing here
}
Where CamelMessage is from package akka.camel. That's what the examples in the akka camel docs are doing.
I guess most of us agree, that NIO2 is a fine thing to make use of. Presumed you want to monitor some part of the file system for incoming xml - files it is an easy task now. But what if I want to integrate the things into an existing Java EE application so I don't have to start another service (app-server AND the one which monitors the file system)?
So I have the heavy weight app-server with all the EJB 3.1 stuff and some kind of service monitoring the file system and take appropriate action once a file shows up. Interestingly the appropriate action is to create a Message and send it by JMS and it might be nice to integrate both into the app server.
I tried #Startup but deployment freezes (and I know that I shouldn't make use of I/O in there, was just a try). Anyhow ... any suggestions?
You could create a singleton that loads at startup and delegates the monitoring to an Asynchronous bean
#Singleton
#Startup
public class Initialiser {
#EJB
private FileSystemMonitor fileSystemMonitor;
#PostConstruct
public void init() {
String fileSystemPath = ....;
fileSystemMonitor.poll(fileSystemPath);
}
}
Then the Asynchronous bean looks something like this
#Stateless
public class FileSystemMonitor {
#Asynchronous
public void poll(String fileSystemPath) {
WatchService watcher = ....;
for (;;) {
WatchKey key = null;
try {
key = watcher.take();
for (WatchEvent<?> event: key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue; // If events are lost or discarded
}
WatchEvent<Path> watchEvent = (WatchEvent<Path>)event;
//Process files....
}
} catch (InterruptedException e) {
e.printStackTrace();
return;
} finally {
if (key != null) {
boolean valid = key.reset();
if (!valid) break; // If the key is no longer valid, the directory is inaccessible so exit the loop.
}
}
}
}
}
Might help if you specified what server you're using, but have you considered implementing a JMX based service ? It's a bit more "neutral" than EJB, is more appropriate for a background service and has fewer restrictions.
I am writing my first Android database backend and I'm struggling to unit test the creation of my database.
Currently the problem I am encountering is obtaining a valid Context object to pass to my implementation of SQLiteOpenHelper. Is there a way to get a Context object in a class extending TestCase? The solution I have thought of is to instantiate an Activity in the setup method of my TestCase and then assigning the Context of that Activity to a field variable which my test methods can access...but it seems like there should be an easier way.
You can use InstrumentationRegistry methods to get a Context:
InstrumentationRegistry.getTargetContext() - provides the application Context of the target application.
InstrumentationRegistry.getContext() - provides the Context of this Instrumentation’s package.
For AndroidX use InstrumentationRegistry.getInstrumentation().getTargetContext() or InstrumentationRegistry.getInstrumentation().getContext().
New API for AndroidX:
ApplicationProvider.getApplicationContext()
You might try switching to AndroidTestCase. From looking at the docs, it seems like it should be able to provide you with a valid Context to pass to SQLiteOpenHelper.
Edit:
Keep in mind that you probably have to have your tests setup in an "Android Test Project" in Eclipse, since the tests will try to execute on the emulator (or real device).
Your test is not a Unit test!!!
When you need
Context
Read or Write on storage
Access Network
Or change any config to test your function
You are not writing a unit test.
You need to write your test in androidTest package
Using the AndroidTestCase:getContext() method only gives a stub Context in my experience. For my tests, I'm using an empty activity in my main app and getting the Context via that. Am also extending the test suite class with the ActivityInstrumentationTestCase2 class. Seems to work for me.
public class DatabaseTest extends ActivityInstrumentationTestCase2<EmptyActivity>
EmptyActivity activity;
Context mContext = null;
...
#Before
public void setUp() {
activity = getActivity();
mContext = activity;
}
... //tests to follow
}
What does everyone else do?
You can derive from MockContext and return for example a MockResources on getResources(), a valid ContentResolver on getContentResolver(), etc. That allows, with some pain, some unit tests.
The alternative is to run for example Robolectric which simulates a whole Android OS. Those would be for system tests: It's a lot slower to run.
You should use ApplicationTestCase or ServiceTestCase.
Extending AndroidTestCase and calling AndroidTestCase:getContext() has worked fine for me to get Context for and use it with an SQLiteDatabase.
The only niggle is that the database it creates and/or uses will be the same as the one used by the production application so you will probably want to use a different filename for both
eg.
public static final String NOTES_DB = "notestore.db";
public static final String DEBUG_NOTES_DB = "DEBUG_notestore.db";
First Create Test Class under (androidTest).
Now use following code:
public class YourDBTest extends InstrumentationTestCase {
private DBContracts.DatabaseHelper db;
private RenamingDelegatingContext context;
#Override
public void setUp() throws Exception {
super.setUp();
context = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_");
db = new DBContracts.DatabaseHelper(context);
}
#Override
public void tearDown() throws Exception {
db.close();
super.tearDown();
}
#Test
public void test1() throws Exception {
// here is your context
context = context;
}}
Initialize context like this in your Test File
private val context = mock(Context::class.java)