Jade Framework (two containers) - java

I have expertise in using Jade in the same host (my laptop) as I can handle all interactions between agents;
But I have to run the MainContainer in my laptop and the second container in a Raspberry Pi.
I started to try a simple example by creating 2 agents, the first on the main container and the second on the container that will run on Raspberry Pi. But it doesn't work.
the following code is for the main container including agent1 which will send message to agent2
Runtime runtime = Runtime.instance();
Properties properties = new ExtendedProperties();
properties.setProperty(Profile.GUI, "true");
Profile profile = new ProfileImpl(properties);
AgentContainer agentContainer1=runtime.createMainContainer(profile);
Container.start();
AgentController agent1=agentContainer1.createNewAgent("Agent1","Connexion.Agent1",new Object[]{});
agent1.start();
Code of the second container:
Runtime runtime=Runtime.instance();
Profile profile=new ProfileImpl();
profile.setParameter(profile.MAIN_HOST, "192.168.0.164"); //Raspberry Pi host
AgentContainer agentContainer1=runtime.createAgentContainer(profile);
AgentController agent2=agentContainer1.createNewAgent("Agent2","Connexion.Agent2",new Object[]{});
agent2.start();
agentContainer1.start();
agent1 send message to agent2 every 15seconds.
There isn't any problem with the main container code but when I run the raspberry container using deployAndBrickPun (ev3dev-lang-java), it show me the following error:
> Task :deploy
Host key checking is off. It may be vulnerable to man-in-the-middle attacks.
ev3dev#1|Sep 20, 2021 1:27:00 PM jade.core.AgentContainerImpl joinPlatform
ev3dev#1|SEVERE: Some problem occurred while joining agent platform.
ev3dev#1|jade.core.ProfileException: Can't get a proxy to the Platform Manager - Caused by: Dispatcher error - Caused by: DispatcherException in remote site. No skeleton for object-id0
ev3dev#1| at jade.core.ProfileImpl.createPlatformManager(ProfileImpl.java:529)
ev3dev#1| at jade.core.ProfileImpl.getPlatformManager(ProfileImpl.java:442)
ev3dev#1| at jade.core.ProfileImpl.getServiceManager(ProfileImpl.java:456)
ev3dev#1| at jade.core.AgentContainerImpl.init(AgentContainerImpl.java:347)
ev3dev#1| at jade.core.AgentContainerImpl.joinPlatform(AgentContainerImpl.java:495)
ev3dev#1| at jade.core.Runtime.createAgentContainer(Runtime.java:127)
ev3dev#1| at Connexion.Container1.main(Container1.java:17)
I need to solve this errors, so I asking for your help please;
Thank you in advance.

you lack information within your profiles.
You need to defined IP,port, hostname on both (main-container and distant-containers). Not doing it on the main-c will create pb for it to run, but you will not be able to join it from the pi.
The IP given on the pi-container should be the one of the main-container. Not sure if its the case in your example.
You can give a look at the open-source project startJade that intends to offer several running examples. The "Platform creation" example covers this case.

Related

No peers provided by network with hyperledger app on android

With the Commercial paper tutorial, I continue to try to implement the java application to an Android emulator.
On Issue.java, when call Network network = gateway.getNetwork("mychannel"); an error occur : IllegalArgumentException: No peers provided.
Because of network argument by getChaincodeQueryPeersForOrganization(DefaultQueryHandlers.java:50), he don't give me a collection of peers and cause error on SingleQueryHandler.java:29.
I think about connection-org2.yaml file, but don't see what's wrong.
(Default Java app not work correctly)
How can I give the right network, with correct peers ?
Complete error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: iti.paper.ch.paper_test, PID: 9568
java.lang.IllegalArgumentException: No peers provided
at org.hyperledger.fabric.gateway.impl.query.SingleQueryHandler.<init>(SingleQueryHandler.java:29)
at org.hyperledger.fabric.gateway.DefaultQueryHandlers.lambda$static$0(DefaultQueryHandlers.java:30)
at org.hyperledger.fabric.gateway.-$$Lambda$DefaultQueryHandlers$A9xv6yy6Ls07YnjWxZKkScD7PTQ.create(Unknown Source:0)
at org.hyperledger.fabric.gateway.DefaultQueryHandlers.create(DefaultQueryHandlers.java:73)
at org.hyperledger.fabric.gateway.impl.NetworkImpl.<init>(NetworkImpl.java:54)
at org.hyperledger.fabric.gateway.impl.GatewayImpl.getNetwork(GatewayImpl.java:252)
at iti.paper.ch.paper_test.Issue.main(Issue.java:56)
at iti.paper.ch.paper_test.MainActivity$1.onClick(MainActivity.java:29)
Your SDK uses the connection-org2.yaml to populate the a view of the network to a large degree on the client side. The rest is taken care of by service discovery, should there be any changes subsequently.
Having said that, you should add your channel details in your connection profile (connection-org2.yaml) and specify the roles of the peers. The error that you are seeing is related to the fact that there are no peers defined with chaincode querying roles. You do that by modiying the connection profile and including details similar to this..
channels: //name if the channel
mychannel:
peers:
peer0.org2.example.com:
endorsingPeer: false //this is a role
chaincodeQuery: true //this is a role
discover: true // this is a role
peer1.org2.example.com:
endorsingPeer: false
chaincodeQuery: true
discover: true
Try this and restart your network. Bear in mind that the default scripts will also regenate any connection profles using the template.

Connecting to Azure Iot Hub using TPM

I have successfully provisioned a device in Azure IoT using TPM authentication by following this sample and the following guide: https://learn.microsoft.com/en-us/azure/iot-dps/quick-enroll-device-tpm-java
Now that my device is provisioned I'm trying to figure out the simplest way to connect to the IoT Hub using the keys stored on the TPM chip. I've tried the following code snippet:
SecurityProviderTpm securityClientTPM = new SecurityProviderTPMHsm();
DeviceClient client = DeviceClient.createFromSecurityProvider("myhub.azure-devices.net", "my-device", securityClientTPM, IotHubClientProtocol.HTTPS);
but this fails with:
Exception in thread "main" java.io.IOException: com.microsoft.azure.sdk.iot.provisioning.security.exceptions.SecurityProviderException: activateIdentityKey first before signing
at com.microsoft.azure.sdk.iot.device.auth.IotHubSasTokenHardwareAuthenticationProvider.generateSasTokenSignatureFromSecurityProvider(IotHubSasTokenHardwareAuthenticationProvider.java:169)
at com.microsoft.azure.sdk.iot.device.auth.IotHubSasTokenHardwareAuthenticationProvider.<init>(IotHubSasTokenHardwareAuthenticationProvider.java:51)
at com.microsoft.azure.sdk.iot.device.DeviceClientConfig.<init>(DeviceClientConfig.java:192)
at com.microsoft.azure.sdk.iot.device.InternalClient.<init>(InternalClient.java:109)
at com.microsoft.azure.sdk.iot.device.DeviceClient.<init>(DeviceClient.java:284)
at com.microsoft.azure.sdk.iot.device.DeviceClient.createFromSecurityProvider(DeviceClient.java:250)
at samples.com.microsoft.azure.sdk.iot.SendEvent.main(SendEvent.java:88)
Caused by: com.microsoft.azure.sdk.iot.provisioning.security.exceptions.SecurityProviderException: activateIdentityKey first before signing
at com.microsoft.azure.sdk.iot.provisioning.security.hsm.SecurityProviderTPMHsm.signWithIdentity(SecurityProviderTPMHsm.java:371)
at com.microsoft.azure.sdk.iot.device.auth.IotHubSasTokenHardwareAuthenticationProvider.generateSasTokenSignatureFromSecurityProvider(IotHubSasTokenHardwareAuthenticationProvider.java:155)
... 6 more
Searching the SDK code shows that activateIdentityKey is only called during the provisioning process though.
Re-invoking the provisioning proceedure everytime I want to connect the client doesn't seem right. Is there a better way to connect the device to the IoT Hub once it's been provisioned?
I was able to work around this by removing the check in the signWithIdentity function and removing the need to pass the publicArea to the signData function.
The publicArea is only used to derive the hash algorithm which can be set to a constant given that we know how the key was created.
My updated signData function looks like:
private byte[] signData(Tpm tpm, byte[] tokenData) throws SecurityProviderException {
TPM_ALG_ID idKeyHashAlg = TPM_ALG_ID.SHA256;
...
This has been working well for us so far, but it would be nice to get some feedback from the library authors :)

Using WOLA in Liberty WebApp to access CICS

Trying to use WOLA direct from a webapp in Liberty to CICS. Using same CICS region successfully with z/OS Connect V2 (zCEE). With Liberty, I have configured:
<featureManager>
<feature>servlet-3.1</feature>
<feature>jndi-1.0</feature>
<feature>jaxrs-1.1</feature>
<feature>zosLocalAdapters-1.0</feature>
</featureManager>
and
<!-- WOLA group to which others register -->
<zosLocalAdapters wolaGroup="GROUP" wolaName2="LIBRTOLA" wolaName3="WOLA3" />
<connectionFactory id="wolaCF" jndiName="eis/ola">
<properties.ola RegisterName=CICSMLAW/>
</connectionFactory>
<resourceAdapter location="/usr/lpp/IBM/zosconnect/v2r0/wlp/lib/ola.rar"/>
In the messages.log, I see good and bad items there:
CWWKB0103I: Authorized service group WOLA is available The WebSphere Optimized Local Adapter channel registered with the Liberty profile server using the following name: GROUP LIBRTOLA WOLA3
and the bad:
com.ibm.ws.app.manager.AppMessageHelper E CWWKZ0013E: It is not possible to start two applications called ola.
So the failure on registration: Requestlgth: 97
Requestparms data 1: BBOC START_SRVR RGN=CICSMLA DGN=GROUP NDN=LIBRTOLA
Requestparms data 2: SVN=WOLA3 SVC= MNC=1 MXC=10 TXN=N SEC=N REU=N
Requestparms data 3:
Processing a START SERVER request.
Starting WAS adapters Server task ...
Server transaction id will be: BBO$
Link transaction defaults to: BBO#
Service name will be:
Trace TDQ: BBOQ
Processing a REGISTER API request.
Register name: CICSMLA string len: 7
WAS Daemon: GROUP WAS Node: LIBRTOLA WAS Server: WOLA3
Min. connections: 1
Max. connections: 10
Transactional: N string len: 1
Security propagation: N string len: 1
Invoking OLA Register API for CICSMLA .
on with the Liberty profile server was not successful. The return code is 8, and the reason code 8.
And the failure in the JNDI call:
Context ctx = new InitialContext();
ConnectionFactory cf = (com.ibm.ws390.ola.jca.ConnectionFactoryImpl)ctx.lookup("java:comp/env/eis/ola");
Results in error:
[err] javax.naming.NameNotFoundException: javax.naming.NameNotFoundException: java:comp/env/eis/ola
[err] at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLContext.lookup(JavaURLContext.java:356) [err] at [internal classes]
[err] at javax.naming.InitialContext.lookup(InitialContext.java:428)
[err] at com.ibm.ctl.bank.impls.CTLBankWolaImpl.(CTLBankWolaImpl.java:51)
[err] at com.ibm.ctl.bank.web.OLTPBankRest.setImpl(OLTPBankRest.java:235)
Thanks
You have a lot going on here.
I'm not sure why you're starting ola.rar from the z/OS Connect v2 product, inside of a Liberty server. The zosLocalAdapters-1.0 feature already loads the ola.rar that ships with Liberty. You should remove the configuration from server.xml. That should resolve the CWWKZ0013E error.
You should see two CWWKB0103I messages in messages.log, one for WOLA (which you included) and one for CLIENT.WOLA. Please be sure you see both. It's possible you're on a very old version of Liberty that doesn't print the second CWWKB0103I message, so if this is true, please disregard that part.
I don't think you would have gotten this far without finding the WOLA configuration instructions for the Liberty server in the knowledge center, but here they are for other's benefits:
https://www.ibm.com/support/knowledgecenter/en/was_beta_liberty/com.ibm.websphere.wlp.nd.multiplatform.doc/ae/twlp_dat_enableconnector.html
OK next, I can't see your application to know whether you've got a resource-reference to a connection factory configured. I assume you do because you're doing a java:comp/env lookup. You do not need to cast to com.ibm.ws390.ola.jca.ConnectionFactoryImpl, and actually I highly recommend removing that since that is an internal class and subject to change at any time. It may be that the application class loader doesn't have access to that class, and that may be part of the problem.
Finally, you have a problem in CICS starting the link server. You are getting RC=8 RSN=8. A list of services and return/reason codes can be found here:
https://www.ibm.com/support/knowledgecenter/en/was_beta_liberty/com.ibm.websphere.wlp.nd.multiplatform.doc/ae/rwlp_dat_olaapis.html
An 8/8 on BBOA1REG (register) indicates the register token is already in use. Basically, the RGN= name you picked is already in use. Are you sure there isn't a PLTPI transaction or something else in the CICS region that is already registered with that name? Perhaps try a different name just to see if it works, and if it does, maybe try BBOC LIST_SRVR to see what it is? It's difficult to say how it's getting started without knowing more about your system.
I hope this helps. Take care!

Unknown Move Destination: STORESCP

I have just installed dcm4chee4-4.4.0.Beta1, following INSTALL.md instructions and everything works fine except movescu test.
When I run this test I can see an error in standalone/log/server.log (previously I launched in another console storescp -b11115). This is the error:
2015-09-13 12:48:49,105 INFO [org.dcm4che3.net.Association] (pool-6-thread-7) DCM4CHEE<-MOVESCU(7): processing 1:C-MOVE-RQ[pcid=1, prior=0
cuid=1.2.840.10008.5.1.4.1.2.2.2 - Study Root Query/Retrieve Information Model - MOVE
tsuid=1.2.840.10008.1.2 - Implicit VR Little Endian failed. Caused by: org.dcm4che3.net.service.DicomServiceException: Unknown Move Destination: STORESCP#localhost:11115
at org.dcm4chee.archive.retrieve.scp.CMoveSCP.calculateMatches(CMoveSCP.java:184) [dcm4chee-arc-retrieve-scp-4.4.0.Beta1.jar:]
I think this is because of configuration, maybe I have to add STORESCP as acceptedAET or similar, but I can find info on how to do it. I search through ldap using Apache Directory Studio, but I didn't find anything.
Thanks in advance.
Using dcm4che3, it goes like this if you're implementing an SCP and need to define which other SCPs are allowed to C-STORE things to you.
// Usual calamity creating Connection, ApplicationEntity and Device
...
ApplicationEntity ae = new ApplicationEntity("MYAETITLE");
String[] acceptedAETs = { "STORESCP", "GEPACS" }; // etc...
ae.setAcceptedCallingAETitles(acceptedAETs);
I assume that your favourite SCP (STORESCP) may need to know where to find the SCP known by MYAETITLE; identified by IP address and port. Typically you connect to an SCP as a SCU, issuing a C-MOVE (in the scenario laid out here) instructing the SCP to do a C-STORE to the AET identified in the C-MOVE.
I'm a bit confused by your choice of AE Title in your question (STORESCP) because that indicates that you kind of mix up the two SCPs involved here; the one receiving the C-MOVE (which should not be called STORESCP :) and the one implementing the C-STORE behaviour. The answer I gave above, is aimed at the SCP implementing the C-STORE behaviour.

Tomcat: Change the Virtual hosts programmatically?

Tomcat offers a build in "Virtual Hosting" Support: An Engine/Web-Application can be configured to be responsible for a list of Domains. These Domains have to be put into the server.xml/context.xml files with a special xml directive.
=> Is there any possibility to change the Tomcat Configuration (in general) and especially the "Virtual Hosts" of a Web-Application/Engine programmatically?
For example if a new user signs up, I have to add his domain to the list of "accepted virtual hosts/domains". The only way I currently think of is changing the xml files via a script and then restart Tomcat.
Is there any way to add them add runtime via some Java-Methods programmatically?
Thank you very much!
Jan
Tomcat provides APIs to create new virtual host. To get access to the wrapper object needed for this, you need to implement a ContainerServlet. You can create virtual host like this,
Context context = (Context) wrapper.getParent();
Host currentHost = (Host) context.getParent();
Engine engine = (Engine) currentHost.getParent();
StandardHost host = new StandardHost();
host.setAppBase(appBase);
host.setName(domainName);
engine.addChild(host);
You need to make sure appBase directory exist and you have to find ways to persist the new host to the server.xml or you lose the host on restart.
However, this approach rarely works. If your users run their own apps, you really want run separate instances of Tomcat so you can sandbox the apps better. e.g. One app running out of memory doesn't kill all other apps.
If you provide the app, you can just use one host (defaultHost). You can get the domain name from Host header and do whatever domain-specific stuff in your code.
You shouldn't change the server environment programmatically and there are no reliable and standard ways to do this. Best is to do and keep it all on the webapp side. To start, a Filter is perfectly suitable for this. Store the names somewhere in a database table or a properties file which you cache in the application scope. Check the HttpServletRequest#getRequestURI() (or the getServerName() if it is a subdomain instead of pathinfo) and do the forwarding task accordingly.
Hope this helps.
Use JMX
ArrayList serverList = MBeanServerFactory.findMBeanServer(null);
MBeanServer server = (MBeanServer) serverList.get(0);
Object[] params = { "org.apache.catalina.core.StandardHost", hostName };
String[] signature = { "java.lang.String", "java.lang.String" };
server.invoke(new ObjectName("Catalina:type=Engine"), "addChild", params, signature);
If needed, retrieve the host object and work with it:
ObjectName host = new ObjectName("Catalina:type=Host,host=" + hostName);
server.setAttribute(host, new Attribute("autoDeploy", false));
server.invoke(host, "start", null, null);
I would suggest you set your application to be the default virtual host in server.xml so your single virtual host can respond to requests addressed to any host name. Tomcat ships with the localhost application set as the default virtual host. So you can see how to do this by simply inspecting the server.xml file of a vanilla tomcat installation. You can programatically determine the host name the user sent the request to using the ServletRequest.getServerName() method.
Tomcat used to ship with a web application called "host-manager". Note: this is different than the "manager" web application that still comes with Tomcat. Host manager allowed for changing configuration or adding new virtual hosts on the fly without restarting the server. You could interact with the host-manager over HTTP (programmatically if desired). However, it had the unfortunate flaw of not committing its changes to server.xml so they were all lost on a web server restart. For whatever reason, starting with version 6, Tomcat no longer ships with the host-manager application. So it doesn't appear to be supported anymore.
To sum up ZZ Coder answer which guided me a lot:
You have to create a servlet that implements ContainerServlet and override setWrapper method to get the org.apache.catalina.Wrapper object.
For doing that you have to have privileged="true" in your context.xml Context tag or it will throw an exception. Then you can use the Wrapper object and:
StandardContext context = (StandardContext) wrapper.getParent();
StandardHost currentHost = (StandardHost) context.getParent();
StandardEngine engine = (StandardEngine) currentHost.getParent();
StandardHost host = new StandardHost();
host.setAppBase(currentHost.getAppBase()); //in my case I created another instance of the same application
host.setDomain(currentHost.getDomain());
host.setAutoDeploy(false); // not restarting app whenever changes happen
host.setName("domain.com");
host.setThrowOnFailure(true);// tell it to throw an exception here if it fails to create the host
host.setDeployOnStartup(true);
host.setStartChildren(true);
host.setParent(engine);
// you can add multiple aliases
host.addAlias(alias);
StandardContext ctx = new StandardContext();
ctx.setDocBase(context.getDocBase()); //again I reused my same application setting
ctx.setPath("");
if(currentHost.getWorkDir() != null)
{//create a working directory based on your new host's name
ctx.setWorkDir(currentHost.getWorkDir().replace(currentHost.getName(), host.getName()));
}
ctx.setName(host.getDomain());
//some extra config that you can use
ctx.setUseHttpOnly(false);
ctx.setReloadable(false);
ctx.setXmlValidation(false);
ctx.setXmlNamespaceAware(false);
ctx.setCrossContext(false);
ctx.setParent(host);
// you have to have this or it will not work!!
ctx.addLifecycleListener(new ContextConfig());
//you can also create resources and add it to the context like so:
final ContextResource res = new ContextResource();
res.setName("name");
res.setAuth("Container");
res.setType("javax.sql.DataSource");
ctx.getNamingResources().addResource(res);
host.addChild(ctx);
engine.addChild(host);
You can add properties to your resource by calling res.setProperty("name", "value")
Some properties that you can use are:
initialSize,maxTotal,maxIdle,maxWaitMillis,removeAbandonedOnBorrow,removeAbandonedTimeout,validationQuery,timeBetweenEvictionRunsMillis,driverClassName,url,username,password.
Another exciting thing to is to get the host from the tomcat engine by calling engine.findChild(domain) and use stop(), start(), getStateName() and have your own Tomcat Admin panel!

Categories

Resources