XmlRpcException while passing params to the ejabberd command - java

I am trying to call the Ejabberd command create_room_with_opts via XMLRPC using the apache XMLRPC api. The following is the code I am using.
XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
config.setServerURL(new URL(<EJABBERD_HOST_URL>));
XmlRpcClient client = new XmlRpcClient();
client.setConfig(config);
// Command string
String command = "create_room_with_opts";
Map<String, Object> struct1 = new HashMap<String, Object>();
struct1.put("user", <ADMIN_USERNAME>);
struct1.put("server", <HOST>);
struct1.put("password", <ADMIN_PASSWORD>);
struct1.put("admin", Boolean.TRUE);
Map<String, Object> struct = new HashMap<String, Object>();
struct.put("name", "testroom");
struct.put("service", <NAME_OF_SERVICE>);
struct.put("host", <HOST>);
struct.put("options", getOpts());
HashMap result = (HashMap) client.execute(command, params);
static Object[] getOpts() {
Object opt[] = new Object[1];
HashMap<String, Object> option = new HashMap<String, Object>();
HashMap<String, Object> optionTuple = new HashMap<String, Object>();
option.put("name", "public");
option.put("value", Boolean.TRUE);
optionTuple.put("option", option);
return opt;
}
However, when I run this code I get the following exception.
org.apache.xmlrpc.XmlRpcException: Error -122
Parameter '{struct,[{name,<<"public">>},{value,<<"true">>}]}' can't be coerced to type '{tuple,[{name,binary},{value,binary}]}'
at org.apache.xmlrpc.client.XmlRpcStreamTransport.readResponse(XmlRpcStreamTransport.java:181)
at org.apache.xmlrpc.client.XmlRpcStreamTransport.sendRequest(XmlRpcStreamTransport.java:149)
at org.apache.xmlrpc.client.XmlRpcHttpTransport.sendRequest(XmlRpcHttpTransport.java:95)
at org.apache.xmlrpc.client.XmlRpcSunHttpTransport.sendRequest(XmlRpcSunHttpTransport.java:39)
at org.apache.xmlrpc.client.XmlRpcClientWorker.execute(XmlRpcClientWorker.java:53)
at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:166)
at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:136)
at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:125)
I am unable to identify the problem in this code.
I have tried the example given in the ejabberd documentation at the API-Documentation,
but it seems that there is a syntax error in that example.
I am able to call the other commands(for example create_room, register, etc) for the same Ejabberd server successfully, so I know that the configuration is correct.
I am using JDK1.7 and apache XMLRPC api 3.1.3
Is there any other example(for create_room_with_opts command) which I can check.

Related

Apache CXF Policy Exception Reference to policy X509 Authentication, Signature and Encryption could not be resolved

Am trying to call third party web service using java apache CXF. I created the proxy using CXF apache plugin. The service is protected using X509 Authentication, Signature and Encryption.
When I call the service, am getting the below exception.
Apache CXF Policy Exception Reference to policy "X509 Authentication, Signature and Encryption" could not be resolved
This is what I tried sofar..
ServiceEnq service=new ServiceEnq(new
URL("https://.....Inquiry?wsdl"));
System.out.println("Line2 scuccess!");
InquiryPortType port=service.getInquiryPort();
Client client = ClientProxy.getClient(port);
org.apache.cxf.endpoint.Endpoint endpoint = client.getEndpoint();
HashMap<String, Object> outProps = new HashMap<String, Object>();
outProps.put(WSHandlerConstants.ACTION,
"UsernameToken Timestamp Signature Encryption");
outProps.put(WSHandlerConstants.USER, "username1");
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordCallbackHandler.class.getName());
outProps.put(WSHandlerConstants.ENCRYPTION_USER, "public1");
outProps.put(WSHandlerConstants.ENC_PROP_FILE, "publicProp.properties");
outProps.put(WSHandlerConstants.SIGNATURE_USER, "pk");
outProps.put(WSHandlerConstants.SIG_PROP_FILE, "pkProp.properties");
outProps.put("timeToLive", "30");
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
endpoint.getOutInterceptors().add(wssOut);
HashMap<String, Object> inProps = new HashMap<>();
inProps.put(WSHandlerConstants.ACTION, "Encryption Signature Timestamp");
inProps.put(WSHandlerConstants.DEC_PROP_FILE, "publicProp.properties");
inProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordCallbackHandler.class.getName());
inProps.put(WSHandlerConstants.SIG_PROP_FILE, "pkProp.properties");
WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps);
endpoint.getInInterceptors().add(wssIn);
ObjectFactory fact=new ObjectFactory();
InquiryRequest request=fact.createInquiryRequest();
MessageHeaderIn headerIn=fact.createMessageHeaderIn();
// removed input parameters
// getting error in this line...
InquiryResponse2 res= port.Inquiry(request);
I have manually created the XML Document and used wss4j to encrypt and sign XML document. Then uploaded the generated SOAP envelope to HttpURLConnection using POST method.
Here is the java code to sign and encryption. I have avoided other code as this is more tricky part..
public void addSignature(org.w3c.dom.Document doc) {
try {
Properties properties = new Properties();
properties.put("org.apache.ws.security.crypto.merlin.keystore.password", SecurityConstants.JKSPassword);
properties.put("org.apache.ws.security.crypto.merlin.keystore.file",
SecurityConstants.ClientCert);
properties.put("org.apache.ws.security.crypto.merlin.keystore.alias",
SecurityConstants.ClientKeyAliasName);
Merlin keyMaterialCrypto = new Merlin(properties);
WSSecSignature wssSign = new WSSecSignature();
wssSign.setUserInfo(SecurityConstants.ClientKeyAliasName, SecurityConstants.JKSPassword);
wssSign.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);
wssSign.setUseSingleCertificate(false);
org.apache.ws.security.message.WSSecHeader secHeader = new WSSecHeader();
secHeader.setMustUnderstand(false);
secHeader.insertSecurityHeader(doc);
wssSign.build(doc, keyMaterialCrypto, secHeader);
} catch (Exception e) {
e.printStackTrace();
System.out.print(e.toString());
}
}
public void addEnccryption(Document doc) {
StringWriter writer = null;
try {
Properties properties = new Properties();
properties.put("org.apache.ws.security.crypto.merlin.keystore.password", SecurityConstants.JKSPassword);
properties.put("org.apache.ws.security.crypto.merlin.keystore.file",
SecurityConstants.ServerCer);
properties.put("org.apache.ws.security.crypto.merlin.keystore.alias",
SecurityConstants.ServerAliasName);
Merlin crypto = new Merlin(properties);
WSSecEncrypt wsEncryption = new WSSecEncrypt();
WSSConfig wssConfig = WSSConfig.getNewInstance();
wsEncryption.setWsConfig(wssConfig);
wsEncryption.setUserInfo(SecurityConstants.ServerAliasName);
wsEncryption.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);
wsEncryption.setEncryptSymmKey(true);
org.apache.ws.security.message.WSSecHeader secHeader = new WSSecHeader();
secHeader.setMustUnderstand(false);
secHeader.insertSecurityHeader(doc);
wsEncryption.build(doc, crypto, secHeader);
} catch (Exception e) {
e.printStackTrace();
}
}

Create nested objects without creating class in Java

I want to create the following object for the response but I don't want to create the class for this. Is there any way I can achieve this using map or other util classes?
"conferenceData": {
"createRequest": {
"conferenceSolutionKey": {
"type": "hangoutsMeet"
},
"requestId": "RANDOM_STRING2"
}
}
I think below is the solution you are looking for...
Map<String, Object> conferenceData = new HashMap<>();
Map<String, Object> createRequest = new HashMap<>();
Map<String, Object> keyAndRequestId= new HashMap<>();
Map<String, String> type = new HashMap<>();
type.put("type", "hangoutsMeet");
keyAndRequestId.put("conferenceSolutionKey", type);
keyAndRequestId.put("requestId", "RANDOM_STRING2");
createRequest.put("createRequest", keyAndRequestId);
conferenceData.put("conferenceData", createRequest);
Try to use :
Map<String,Object> result = new ObjectMapper().readValue(JSON_SOURCE, HashMap.class);
Or if you are using org.json, JSONObject has a method toMap(). You can easily do :
Map<String, Object> myMap = myJsonObject.toMap();

Create Event in AEM 6.4

How can I create an programatically Event for UnitTests in AEM 6.4 after EventPropertiesMap has been removed?
List<EventPropertiesMap> fakeModifications = new ArrayList<>();
fakeModifications.add(PageModification.deleted(pagePath,
StringUtils.EMPTY).getEventProperties());
Map eventProps = new HashMap();
eventProps.put("modifications", fakeModifications);
return new Event("com/day/cq/wcm/core/page", eventProps);
I came up with this solution hoping to share the pain of an upgrade with others :-)
If you got a better solution I'm more than welcome!
List<Map<String, ?>> fakesList = new ArrayList<Map<String, ?>>();
Map<String, ?> fakeModifications = PageModification.deleted(pagePath, StringUtils.EMPTY).getEventProperties();
fakesList.add(fakeModifications);
Map<String, List<Map<String, ?>>> eventProps = new HashMap<String, List<Map<String, ?>>>();
eventProps.put("modifications", fakesList);
return new Event("com/day/cq/wcm/core/page", eventProps);

OUTBOUND_MESSAGE_ATTACHMENTS not arriving to server side

I'm calling a service in which I'm setting the OUTBOUND_MESSAGE_ATTACHMENTS in the following way:
Map<String, DataHandler> attachmentsMap = (Map<String, DataHandler>) context.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);
ByteArrayDataSource bads = new ByteArrayDataSource(file, PDF_MIME_TYPE);
DataHandler dh = new DataHandler(bads);
AttachmentPart attachmentPart = message.createAttachmentPart();
attachmentPart.setContent(new ByteArrayInputStream(file), PDF_MIME_TYPE);
attachmentPart.setContentId(fileId);
String contentDisposition = "Content-Disposition: attachment; name=\"" + fileId + "\"";
attachmentPart.addMimeHeader("Content-Disposition", contentDisposition);
message.addAttachmentPart(attachmentPart);
attachmentsMap.put(fileId, dh);
And on server side I expect to find the same information in the INBOUND_MESSAGE_ATTACHMENTS but seems that nothing is sent.
Can you please what I'm doing wrong?
After all I found the solution by myself.
I had to you CXF implementation from Apache and I have to enable the property for writing the attachment.
JaxWsClientFactoryBean clientFactoryBean = new JaxWsClientFactoryBean();
clientFactoryBean.setServiceClass(DocumentManagementForUnderwritingService.class);
clientFactoryBean.setAddress(serviceURL);
JaxWsProxyFactoryBean pfb = new JaxWsProxyFactoryBean(clientFactoryBean);
DocumentUploadHandler.enableSoapClientOutputAttachments(pfb);
DocumentManagementForUnderwritingService proxyy = (DocumentManagementForUnderwritingService) pfb.create();
Below I set the property:
DocumentUploadHandler.enableSoapClientOutputAttachments(pfb);
And the method from the handler is:
public static void enableSoapClientOutputAttachments(JaxWsProxyFactoryBean pfb){
Map<String,Object> props = new HashMap<String, Object>();
props.put(AttachmentOutInterceptor.WRITE_ATTACHMENTS, Boolean.TRUE);
pfb.setProperties(props);
pfb.getOutInterceptors().add(new SwAOutInterceptor());
pfb.getOutInterceptors().add(new AttachmentOutInterceptor());
}
After I created the proxy, I chained the handler:
Binding binding = proxy.getBinding();
#SuppressWarnings("rawtypes")
final List<Handler> handlerChain = binding.getHandlerChain();
handlerChain.add(documentUploadHandler);
binding.setHandlerChain(handlerChain );
And the code from the handler is present in the question.
Hope this will help someone else in the future.

How to make access based xmlrpc call for ejabberd from Java client?

I am running ejabberd and ejabberd_xmlrpc module - https://www.ejabberd.im/ejabberd_xmlrpc
In the link I can see python, php and xmlrpc client module with access control. How can we write the same using java client
Here is my code:
/* Code for ejabberd */
try {
XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
config.setServerURL(new URL("http://ejabberd.sandwitch.in:4560"));
config.setBasicUserName("nishant#ejabberd.sandwitch.in");
config.setBasicPassword("freebsd");
config.setConnectionTimeout(xmlrpcConnTimeout);
config.setReplyTimeout(xmlrpcReplyTimeOut);
XmlRpcClient client = new XmlRpcClient();
client.setConfig(config);
/* Command string */
String command = "register";
/* Parameters as struct */
Map struct = new HashMap();
struct.put("user", "nishant");
struct.put("host", "ejabberd.sandwitch.in");
struct.put("password", "nishant");
Map struct1 = new HashMap();
struct1.put("user", "arbit6");
struct1.put("host", "ejabberd.sandwitch.in");
struct1.put("password", "arbit6");
Object[] params = new Object[]{struct, struct1};
HashMap<Object, Object> hashMap = (HashMap<Object, Object>) client.execute(command, params);
for (Object obj : hashMap.keySet()) {
System.out.println(ToStringBuilder.reflectionToString(obj));
}
for (Object obj : hashMap.values()) {
System.out.println(ToStringBuilder.reflectionToString(obj));
}
System.out.println(ToStringBuilder.reflectionToString(hashMap.get("text")));
} catch (Exception e) {
System.out.println(e);
}
But it is giving an unknown call register.
Fixed it by changing host in first struct to server. My mistake.

Categories