How to create containers and add agents into it in JADE? - agents-jade

I'm just a beginner at JADE. I would like to know how to create containers other than the main container and add multiple agents into it. A full code of creation would be appreciated.
Thanks!

As stated in Tafadzwa Chikudo answer, the usual way to start a container is by launching jade.Boot from the command line (or in a shell script).
But it is also possible to do it inside another Java program, using the "JADE in-process interface" (package jade.wrapper, class jade.core.Runtime).
For instance, the following code creates a "peripheral" container (connecting to a main container on localhost) and launch one agent in it.
//Get the JADE runtime interface (singleton)
jade.core.Runtime runtime = jade.core.Runtime.instance();
//Create a Profile, where the launch arguments are stored
Profile profile = new ProfileImpl();
profile.setParameter(Profile.CONTAINER_NAME, "TestContainer");
profile.setParameter(Profile.MAIN_HOST, "localhost");
//create a non-main agent container
ContainerController container = runtime.createAgentContainer(profile);
try {
AgentController ag = container.createNewAgent("agentnick",
"my.agent.package.AgentClass",
new Object[] {});//arguments
ag.start();
} catch (StaleProxyException e) {
e.printStackTrace();
}

A Peripheral container can be started as follows
java jade.Boot -container -host x.x.x.x -agents z:package.agent;y:package.agent
where x.x.x.x is ip of main contaner, z is the name you give to the first agent, y is the name you give to the second agent and package is the package that contains the agents in a jar file

Related

NServiceBus endpoint is not starting on Azure Service Fabric local cluster

I have a .NetCore stateless WebAPI service running inside Service Fabric local cluster.
return Endpoint.Start(endpointConfiguration).GetAwaiter().GetResult();
When I'm trying to start NServiceBus endpoint, I'm getting this exception :
Access to the path 'C:\SfDevCluster\Data_App_Node_0\AppType_App10\App.APIPkg.Code.1.0.0.diagnostics' is denied.
How can it be solved ? VS is running under administrator.
The issue you are having is because the folder you are trying to write to is not supposed to be written by your application.
The package folder is used to store you application binaries and can be recreated dynamically whenever an application is hosted in the node.
Also, the binaries are reused by multiple service instances running on same node, so it might compete to use the files by different instances.
You should instead instruct your application to write to the WorkFolder,
public Stateless1(StatelessServiceContext context): base(context)
{
string workdir = context.CodePackageActivationContext.WorkDirectory;
}
The code above will give you a path like this:
'C:\SfDevCluster\Data_App_Node_0\AppType_App10\App.APIPkg.Code.1.0.0.diagnostics\work'
This folder is dynamic, will change depending on the node or instance of your application is running, when created, your application should already have permission to write to it.
For more info, see:
how-do-i-get-files-into-the-work-directory-of-a-stateless-service?forum=AzureServiceFabric
Open folder properties Security tab
Select ServiceFabricAllowedUsers
Add Write permission

'Address already in use' when running tests using Spring LDAP embedded server

I am trying to use Spring LDAP in one of my Spring Boot projects but I am getting an 'Address already in use' error when running multiple tests.
I have cloned locally the sample project here:
https://spring.io/guides/gs/authenticating-ldap/
...and just added the boilerplate test normally created by Spring Boot to verify that the Application Context loads correctly:
#RunWith(SpringRunner.class)
#SpringBootTest
public class MyApplicationTests {
#Test
public void contextLoads() {
}
}
If run alone, this test passes. As soon as LdapAuthenticationTests and MyApplicationTests are run together, I get the error above for the latter.
After debugging a bit, I've found out that this happens because the system tries to spawn a second instance of the embedded server.
I am sure I am missing something very stupid in the configuration.
How can I fix this problem?
I had a similar problem, and it looks like you had a static port configured (as was in my case).
According to this article:
Spring Boot starts an embedded LDAP server for each application
context. Logically, that means, it starts an embedded LDAP server for
each test class. Practically, this is not always true since Spring
Boot caches and reuses application contexts. However, you should
always expect that there is more than one LDAP server running while
executing your tests. For this reason, you may not declare a port for
your LDAP server. In this way, it will automatically uses a free port.
Otherwise, your tests will fail with “Address already in use”
Thus it might be a better idea not to define spring.ldap.embedded.port at all.
I addressed the same issue. I solved it with an additional TestExecutionListener since you can get the InMemoryDirectoryServer bean.
/**
* #author slemoine
*/
public class LdapExecutionListener implements TestExecutionListener {
#Override
public void afterTestClass(TestContext testContext) {
InMemoryDirectoryServer ldapServer = testContext.getApplicationContext().getBean(InMemoryDirectoryServer.class);
ldapServer.shutDown(true);
}
}
And on each SpringBootTest (or only once in an abstract super class)
#RunWith(SpringRunner.class)
#SpringBootTest
#TestExecutionListeners(listeners = LdapExecutionListener.class,
mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)
public class MyTestClass {
...
}
also do not forget
mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
to avoid disabling the whole #SpringBootTest auto configuration.
Okay, I think I found a solution by adding a #DirtiesContext annotation to my test classes:
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
If you are using spring embedded ldap, try to comment or remove port value from config file as below :
spring :
ldap:
embedded:
base-dn: dc=example,dc=org
credential:
username: cn=admin,dc=example,dc=org
password: admin
ldif: classpath:test-schema.ldif
# port: 12345
validation:
enabled: false
Try specifying the web environment type and the base configuration class (the one with !SpringBootApplication on it).
#RunWith(SpringRunner.class)
#SpringBootTest(
classes = MyApplication.class,
webEnvironment = RANDOM_PORT
)
public class MyApplicationTests {
#Test
public void contextLoads() {
}
}
Do this for all your test classes.
I solved this problem by adding #DirtiesContext over each test class that requires embedded ldap server. In my case (and as I feel in many others), embedded ldap server was starting up at every #SpringBootTest, since I added all spring.ldap.embedded.* properties to general application-test.properties. Therefore, when I run a bunch of tests, the problem of 'Address already in use' broke all test passing.
Steps I followed:
create an additional test profile (with corresponding named application properties file, e.g. 'application-ldaptest.properties')
move to that file all spring.ldap.embedded.* properties (with fixed port value)
over all #SpringBootTest-s that do require embedded server running up, add #ActiveProfiles("testladp") and #DirtiesContext annotations.
Hope, that helps.

Setting Up Fabric SSH, Error:Timed Out

I'm new to Fabric, so this might have a simple answer I've missed due to bad search terminology.
I'm trying to start a new ubuntu EC2 instance in AWS, then connect to it with Fabric and have it execute several commands. However, it seems there is a problem with Fabric's SSH connection, maybe I'm defining some env variable wrong?
#task //starts new EC2 instance and sets env variables
def prep_deploy():
//code to start new EC2 instance, named buildhost
env.hosts=[buildhost.public_dns_name]
env.user = "ubuntu"
env.key_filename = ".../keypair.pem"
env.port = 22
#task
def deploy():
run("echo $HOME") //code fails here
....
I run fab prep_deploy deploy, since I read you need a new task for the new env variables to take effect.
I get
Fatal error: Timed out trying to connect to ...amazonaws.com (tried 1 time)
Underlying exception: timed out
The security groups for the instance are open to SSH: I can connect through Putty. In fact, if I empty the `env.host_string' variable at the start of deploy(), when it prompts me to manually input a host, I can write in "ubuntu#...amazonaws.com:22", with the host name exactly as seen from output at the task start, and it will connect to the instance. But I can't figure how to manipulate the environment variables so that it understands the host name.
It looks like your fabric settings are correct with the use of variables. I was able to use the code you provided to connect to my Ubuntu VM. I am wondering if you are having a connection issue due to the amazon Instance not being fully booted and ready for connections when your script runs the second task. I have run into that issue on a different VM hosts.
I added the following code to check and try the connection again. This might help you
import socket
import time
def waitforssh():
s=socket.socket()
address=env.host_string
port=22
while True:
time.sleep(5)
try:
s.connect((address,port))
return
except Exception,e:
print "failed to connec to %s:%s %(address,port)
pass
insert the function call into your deploy task
def deploy():
waitforssh()
This should test the connection. If the port does not respond, it will wait 5 seconds and try again.
That could explain why your second attempt to connect works.

GridGain - programmatically opening nodes using SSH through Grid.startNodes API

I am using Grid.startNodes(java.util.Collection, java.util.Map, boolean, int, int)
as defined here: http://gridgain.com/api/javadoc/org/gridgain/grid/Grid.html#startNodes(java.util.Collection, java.util.Map, boolean, int, int)
Code I am using:
GridConfiguration cfg = GridCfgGenerator.GetConfigurations(true);
Grid grid = GridGain.start(cfg);
Collection<Map<String,Object>> coll = new ArrayList<>();
Map<String, Object> host = new HashMap<String, Object>();
//host.put("host", "23.101.201.136");
host.put("host", "10.0.0.4");
host.put("port", 22);
host.put("uname", "username");
host.put("passwd", "password");
host.put("nodes", 7);
//host.put("ggHome", null); /* don't state so that it will use GRIDGAIN_HOME enviroment var */
host.put("cfg", "/config/partitioned.xml");
coll.add(host);
GridFuture f = grid.startNodes(coll, null, false, 3600 * 3600, 4);
System.out.println("before f.get()");
f.get();
I ran the above code on a vm with a 10.0.0.7
I have remote desktop into the VM whos host IP is 10.0.0.4 and see no changes to state. The code completes and exits. Both VMs are able to run gridgain locally and can discover each other's nodes if I start it using bin/ggstart.bat
I can manually start a node on 10.0.0.4 (the machine I am trying to SSH into via this API). I can start said node by running $GG_HOME/bin/ggstart.bat $GG_HOME/config/partitioned.xml so there is no issue in the configuration file
I am not quite sure how to debug this as I get no errors
Successful completion of the future returned from startNodes(..) method means that your local node has established SSH session and executed a command for each node it was going to start. But successful execution of a command doesn't mean that a node will be actually started, because it can fail for several reasons (e.g., wrong GRIDGAIN_HOME).
You should check the following:
Are there GridGain logs created GRIDGAIN_HOME/work/log directory? If yes, then check them - there could be an exception during startup process.
If there are no new logs, there is something wrong with the executed command. The command can be found in the local node logs - search for "Starting remote node with SSH command: ..." lines. You can try to create an SSH connection in terminal, run this command and see what happens.
Also you may want to check your SSH logs to see whether there are any errors.

EJB lookup problem

I have a Glassfish v2.1.1 cluster setup. I deployed an EAR file consisting a single stateless bean to stand alone server. It has an IIOP port 3752.
My client application which will be communicating with this bean is deployed on cluster. When i lookup bean's name, i get NameNotFoundException. Code looks as below:
Properties props = new Properties();
props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
if (logger.isDebugEnabled()) {
logger.debug("Looking for bean from location : " + PropertiesService.instance().getSchedulerOrbHost() + ":"
+ PropertiesService.instance().getSchedulerOrbPort());
}
props.setProperty("org.omg.CORBA.ORBInitialHost", PropertiesService.instance().getSchedulerOrbHost());
props.setProperty("org.omg.CORBA.ORBInitialPort", PropertiesService.instance().getSchedulerOrbPort());
InitialContext context = null;
try {
context = new InitialContext(props);
} catch (NamingException e) {
e.printStackTrace();
}
String beanName = "test.OperationControllerRemote";
OperationControllerRemote remote = (OperationControllerRemote) context.lookup(beanName);
Note that i checked JNDI tree and name "test.OperationControllerRemote" is there.
Any opinions please?
Here are the ways I have got it to work with a GF 2.1.1 cluster and a Swing client. I'm currently going with the Standalone option because of client launch speed, but the ACC might work for you.
Standalone
The way you're doing it is considered standalone.
http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#StandaloneRemoteEJB
http://blogs.oracle.com/dadelhardt/entry/standalone_iiop_clients_with_glassfish
ACC
Another way to approach this is to launch the client with the ACC. This means packaging the client code into the ear as an Application Client and either launching using the JNLP method or manually installing a bundled ACC (mini glassfish really) on client machines. In GF 2.1, either way works ok, but both are pretty fat and JNLP method can make startup times a bit longer. Supposedly in GF 3.1 they've reworked the ACC and it starts up faster. Something that may not be obvious is that with the ACC you get the list of servers in the cluster provided automatically at client startup.
http://blogs.oracle.com/theaquarium/entry/java_ee_clients_with_or
http://download.oracle.com/docs/cd/E18930_01/html/821-2418/beakv.html#scrolltoc
http://download.oracle.com/docs/cd/E18930_01/html/821-2418/gkusn.html
Lookups
Either of the above ways provides RMI/CORBA failover and load balancing for the client.
Either way, when you have the right dependencies on your classpath and the com.sun.appserv.iiop.endpoints system property set (like node1:33700,node2:33701), you'll only need the no-args InitialContext because Glassfish's stuff autoregisters their connection properties, etc as described in the first link:
new InitialContext()
And lookups will work. For my remote session beans (EJB 3.0) I typically do it like:
#Stateless(mappedName="FooBean")
public class FooBean implements FooBeanRemote {}
#Remote
public interface FooBeanRemote {}
then in client code:
FooBeanRemote foo = (FooBeanRemote) ctx.lookup("FooBean");