Sending and Receiving File Strings in ActiveMq 5.15.2 - activemq

I have to send huge files through ActiveMQ and for that purpose I followed the documentation provided for Large message but it is throwing error, packing the file in BytesMessage.
My question is, What is the correct approach for sending file in ActiveMQ 5.15.2
BytesMessage message = session.createBytesMessage();
FileInputStream fileInputStream = new FileInputStream(txFile);
BufferedInputStream bufferedInput = new BufferedInputStream(fileInputStream);
message.setObjectProperty("JMS_AMQ_InputStream", bufferedInput);
producer.send(message);
pom.xml
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.2</version>
</dependency>
Exception:
Caught: javax.jms.MessageFormatException: Only objectified primitive objects, String, Map and List types are allowed but was: java.io.BufferedInputStream#445958d type: class java.io.BufferedInputStream
javax.jms.MessageFormatException: Only objectified primitive objects, String, Map and List types are allowed but was: java.io.BufferedInputStream#445958d type: class java.io.BufferedInputStream
at org.apache.activemq.command.ActiveMQMessage.checkValidObject(ActiveMQMessage.java:538)
at org.apache.activemq.command.ActiveMQMessage.setObjectProperty(ActiveMQMessage.java:504)
at org.apache.activemq.command.ActiveMQMessage.setObjectProperty(ActiveMQMessage.java:488)
at org.apache.activemq.command.ActiveMQBytesMessage.setObjectProperty(ActiveMQBytesMessage.java:918)
at com.svm.mq.test.Producer.run(Producer.java:80)
at java.lang.Thread.run(Thread.java:745)`

The code you pasted (i.e. setting the "JMS_AMQ_InputStream" object property) is for the ActiveMQ Artemis Core client. That won't work for ActiveMQ 5.x.
If you want to "send" a large message with ActiveMQ 5.x then you will need to use a "blob" message as noted by another user. However, this still requires you to send the actual message using another method. The "blob" message is really just a kind of pointer or reference to the message.

Blob Messages is your way to go. Try this link for more details:
BlobMessage message = session.createBlobMessage(new File("/foo/bar");
producer.send(message);

Related

How can I configure a specific serialization method to use only for Celery ping?

I have a celery app which has to be pinged by another app. This other app uses json to serialize celery task parameters, but my app has a custom serialization protocol. When the other app tries to ping my app (app.control.ping), it throws the following error:
"Celery ping failed: Refusing to deserialize untrusted content of type application/x-stjson (application/x-stjson)"
My whole codebase relies on this custom encoding, so I was wondering if there is a way to configure a json serialization but only for this ping, and to continue using the custom encoding for the other tasks.
These are the relevant celery settings:
accept_content = [CUSTOM_CELERY_SERIALIZATION, "json"]
result_accept_content = [CUSTOM_CELERY_SERIALIZATION, "json"]
result_serializer = CUSTOM_CELERY_SERIALIZATION
task_serializer = CUSTOM_CELERY_SERIALIZATION
event_serializer = CUSTOM_CELERY_SERIALIZATION
Changing any of the last 3 to [CUSTOM_CELERY_SERIALIZATION, "json"] causes the app to crash, so that's not an option.
Specs: celery=5.1.2
python: 3.8
OS: Linux docker container
Any help would be much appreciated.
Changing any of the last 3 to [CUSTOM_CELERY_SERIALIZATION, "json"] causes the app to crash, so that's not an option.
Because result_serializer, task_serializer, and event_serializer doesn't accept list but just a single str value, unlike e.g. accept_content
The list for e.g. accept_content is possible because if there are 2 items, we can check if the type of an incoming request is one of the 2 items. It isn't possible for e.g. result_serializer because if there were 2 items, then what should be chosen for the result of task-A? (thus the need for a single value)
This means that if you set result_serializer = 'json', this will have a global effect where all the results of all tasks (the returned value of the tasks which can be retrieved by calling e.g. response.get()) would be serialized/deserialized using the json-serializer. Thus, it might work for the ping but it might not for the tasks that can't be directly serialized/deserialized to/from JSON which really needs the custom stjson-serializer.
Currently with Celery==5.1.2, it seems that task-specific setting of result_serializer isn't possible, thus we can't set a single task to be encoded in 'json' and not 'stjson' without setting it globally for all, I assume the same case applies to ping.
Open request to add result_serializer option for tasks
A short discussion in another question
Not the best solution but a workaround is that instead of fixing it in your app's side, you may opt to just add support to serialize/deserialize the contents of type 'application/x-stjson' in the other app.
other_app/celery.py
import ast
from celery import Celery
from kombu.serialization import register
# This is just a possible implementation. Replace with the actual serializer/deserializer for stjson in your app.
def stjson_encoder(obj):
return str(obj)
def stjson_decoder(obj):
obj = ast.literal_eval(obj)
return obj
register(
'stjson',
stjson_encoder,
stjson_decoder,
content_type='application/x-stjson',
content_encoding='utf-8',
)
app = Celery('other_app')
app.conf.update(
accept_content=['json', 'stjson'],
)
You app remains to accept and respond stjson format, but now the other app is configured to be able to parse such format.

How can I use Format Arguments in BusinessException?

I have noticed the abp localization provide a Format Arguments mechanism to help generate realtime local string by this way, and I want to know how can I do the same thing in calling a BusinessException while all its overloads are not suitable for this purpose.
Please see the documentation: https://docs.abp.io/en/abp/latest/Exception-Handling#exception-localization
It is possible to set an exception code and data related to the exception. Then ABP automatically localizes the exception message by also using the data arguments you've provided.
Example exception:
throw new BusinessException("App:010046")
.WithData("UserName", "john");
And the related localization entry in the json file:
"App:010046": "Username should be unique. '{UserName}' is already taken!"
It is not using {0}, {1}... but using parameter names instead.

How to read properties from .properties file in Mule

I'm trying to use Mule Credentials Vault security feature.
I've created .properties file, Security Property Placeholder and defined the key and encryption algorithm.
Now I want to use some of the properties from the file when I return HTTP response.
I have the file src/main/resources/data.properties that contains for example:
In my canvas, under Configuration XML I added:
<secure-property-placeholder:config name="Secure_Property_Placeholder" key="24681357" location="data.properties" doc:name="Secure Property Placeholder" encryptionAlgorithm="DES"/>
<set-variable variableName="card.number" value="${number}" />
In my canvas I have message flow that builds xml 'Create XML response based on User'. The value in settings is:
This doesn't work. The error I get is:
-> org.mule.module.launcher.DeploymentInitException: IllegalArgumentException: Could not resolve placeholder 'key' in string value "${key}"
-> Caused by: org.mule.api.lifecycle.InitialisationException: Invalid bean definition with name 'org.mule.autogen.bean.13' defined in null: Could not resolve placeholder 'key' in string value "${key}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'key' in string value "${key}"
-> Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'key' in string value "${key}"
Does anyone know how can I read the properties from .properties file (credentials vault)? And then use it in my flow?
Thanks,
Keren
If you simply want to get the value for the property number and add it into the XML you can use ${number} from .properties. No need to define any other variables in Configuration XML.
<set-payload value="<user><name>Royal Bank of Canada</name><id>Royal_Bank_Of_Canada</id><cc><company>>Visa</company><number>${number}</number><secret>123</secret></cc></user>" doc:name="Set Payload"/>
However note that the property placeholder is resolved at startup so you will not be able to dynamically retrieve a property based on some user input. For this you will have to do some Java coding. This SO post gives you some hints on how this can be achieved. Based on those answers I have created a simple example on how this can be done with a very simple helper bean.
I'm afraid you just can't. The Mule Credentials Vault is an enterprise feature and therefore tipically you won't have access to the source code unless you are a MuleSoft customer.
Even if you were a customer, the api you'd use would be sort of unsupported. I suggest to manually create a custom java component levearing your code and Jasypt (not as a property placeholder but as a library).
The other option, if you are a customer (I guess you are given you are using the credentials vault) is to contact the official support so they take care of it for you.
The property placeholder is used resolve at startup so you will not be able to dynamically retrieve a property based on some user input.
Use ${propertyName} from .properties in MEL to access particular property
From Dataweave you can read it as given below
p('variablename')
where variablename is defined in property files ex: variablename = 15

Biztalk 2009: SQL to WCF-SQL adapter migration; orchestration not receiving message?

From topic,
I have a receive location that currently uses sql adapter(receive port) to call(poll?) a stored procedure. The stored proc returns a FOR XML result.
The receiver then activates an orchestration which takes the message and populate the data from the message and into some variables (expression shape).
Orchestration looks like:
LongScope[ AtomicScope[ Receive location -> Expression ] ][Error handling]
I tried a direct migration to wcf-sql with XMLpolling as InboundOperationType, but it throws a null exception during the variable assignation(I assume).
Additional detail:
I caught the message from the receiver by filtering pipelineName using a send port. There is a slight different in the message retrieved by sql and wcf-sql adapter
sql:
<rootNode xmlns="namespace"><row data1="data1" data2 = "data2" /></rootnode>
wcf-sql:
<rootNode xmlns="namespace"><row data1="data1" data2 = "data2" xmlns=""/></rootnode>
Which should do nothing, if this msdn post is correct
I also went into orchestration debugger. Weird thing is, when using sql adapter, the message is still = null, but the varibles are assigned without problem. I also tried adding a send port directly after the receive port to dump the message. Nothing came out
I would appreciate any info/suggestion/solution
Do tell me if im missing any info.
Irrelevant Info:
As of this post the receive port doesnt even trigger anymore. I dont know why. Rebooting PC.
Also I suspect Biztalk gave my bruxism and lead to me requiring 6 teeth fillings
The difference between XML in SQL en WCF-SQL has nothing to do with the MSDN post you are linking to.
In the 2nd XML (WCF-SQL adapter), the row node does not have a namespace. In the 1st XML (SQL adapter), the row node inherits the default namespace "namespace" from its parent: 'root'.
Regarding the Receive Port not triggering anymore:
Are you sure your Host Instance(s) are still running?
My solution:
I added "xmlns = 'namespace'" as a 'data' in the stored procedure.
The adapter recognized it and removed it(since it was the same as parent node), allowing me to use the old schema.
Filler:
So I generated a schema using the output from WCF-SQL adapter,
however I couldnt replace my old one with it, since the expression shape will not recognize its child elements (var = messageObject.childElement)
I created a map to map the new one back to the old one.
But that didnt work, because they both shared the same namespace, and biztalk complained during runtime that it couldnt decide which schema to use.

BizTalk Receive binary file correlated on RecievedFileName

I'm having problem with routing a message of binary file to a running instance of an Orchestration using correlation of context property: ReceivedFileName. The correlation is initialized using a send with dummy file where in the Orchestration sets the ReceivedFileName context property of the message and the property gets promoted. After that routing fails of the message being received (as XmlDocument) and I can see that the ReveivedFileName context property of that message has not been promoted should it be like that? I cant figure out any way to get it promoted so I just want to make sure it should be like this.
The file names are identical but I noticed that the ReceivedFileName property of the send message doesn't have the path whereas the received message has path + file name. I have tried to add the path to the send message(sounds strange though, read it some where) but it doesn't change the outcome.
While you can set Context Proerties in an Orchestration, they are not Promoted.
You have to use the Correlation Technique described here to have the Properties Promoted when they hit the MessageBox: http://blogs.biztalk360.com/property-promotion-inside-orchestration/
Basically, you Initialize a Correlation Set based on the Properties you need Promoted.
As Ben Runchey pointed out in a comment above one have to resort to a custom pipeline and promote the FILE.ReceivedFileName there by calling:
messag.Context.Promote("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/file-properties", receivedFileName);
I also removed the path from FILE.ReceivedFileName to only have the filename by calling the inmsg.Context.Read("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/file-properties")
and altered the value and wrote it back by calling:
inmsg.Context.Write("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/file-properties", receivedFileName);