What is the best way to send a file reference through ActiveMQ, when using SpringBoot 1.3.2.RELEASE? - file

I was using SpringBoot 1.3.1.RELEASE and I was having no problems to send file references through a message in ActiveMQ.
Since I have updated to SpringBoot 1.3.2.RELEASE I have been experimenting a problem.
The activemq client refuse to read the file reference with the following error:
Caused by: java.lang.ClassNotFoundException: Forbidden class java.io.File! This class is not trusted to be serialized as ObjectMessage payload. Please take a look at http://activemq.apache.org/objectmessage.html for more information on how to configure trusted classes.
at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.checkSecurity(ClassLoadingAwareObjectInputStream.java:112) ~[activemq-client-5.12.2.jar:5.12.2]
at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.resolveClass(ClassLoadingAwareObjectInputStream.java:57) ~[activemq-client-5.12.2.jar:5.12.2]
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613) ~[na:1.8.0_05]
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518) ~[na:1.8.0_05]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774) ~[na:1.8.0_05]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[na:1.8.0_05]
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) ~[na:1.8.0_05]
at org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:206) ~[activemq-client-5.12.2.jar:5.12.2]
... 16 common frames omitted
My only solution to solve this problem was to add the first two lines in the creation of the bean JmsTransactionManager.
#Bean
public JmsTransactionManager jmsTransactionManager(ConnectionFactory cf){
ActiveMQConnectionFactory amqCf = (ActiveMQConnectionFactory)cf;
amqCf.setTrustAllPackages(true); // Without this we are not able to send the object type File.class through a JMS message. This problem started when we migrated to Springboot 1.3.2-RELEASE
JmsTransactionManager result = new JmsTransactionManager();
result.setConnectionFactory(cf);
return result;
}
Is there a more recommended way to solve this problem?

Java serialization has many security vulnerabilities that expose you to risk. The updated broker now blacklists most objects and requires you to create a whitelist of the things you want to handle.
Documentation for this is on the ActiveMQ Website.

Related

Full duplex TCP connections using Netty4 and Apache Camel

For an IoT project I am working on I am researching a next, enhanced, version of our “Socket Handler” which is over 5 years of age and has evolved in a big beast doing apart from handling socket connections with IoT devices also in thread processing that has become a real pain to manage.
For my total rewrite I am looking into Apache Camel as a routing and transformation toolkit and understand how this can help us split processing steps into micro-services, loosely coupled through message queues.
One thing that I have trouble understanding however is how I can implement the following logic “the Apache Camel way”:
An IoT device sends an initial message which contains its id, some extra headers and a message payload.
Apart from extracting the message payload and routing it to a channel, I also need to use the device Id to check a message queue, named after the device id, for any commands that have to go to the device over the same socket connection that received the initial message.
Although it seems that Netty4, which is included in Camel, can deal with synchronous duplex comms, I cannot see how the above logic can be implemented in the Camel Netty4 component. Camel Routing seems to be one way only.
Is there a correct way to do this or should I forget about using camel for this and just use Netty4 bare?
It is possible to reproduce a full duplex communication by using two Camel routes :
thanks by using reuseChannel property
As this full duplex communication will be realised thanks to two different Camel routes, sync property must be set to false.
Here the first route:
from("netty4:tcp://{{tcpAddress}}:{{tcpPort}}?decoders=#length-decoder,#string-decoder&encoders=#length-encoder,#bytearray-encoder&sync=false&reuseChannel=true") .bean("myMessageService", "receiveFromTCP").to("jms:queue:<name>")
This first route will create a TCP/IP consumer thanks to a server socket (it is also possible to use a client socket thanks to property clientMode)
As we want to reuse the just created connection, it is important to initialize decoders but also encoders that will be used later thanks to a bean (see further). This bean will be responsible of sending data by using the Channel created in this first route (Netty Channel contains a pipeline for decoding / encoding messages before receiving from / sending to TCP/IP.
Now, we want to send back some data to the parter connected to the consumer (from) endpoint of the first route. Since we are not able to do it thanks to classical producer endpoint (to), we use a bean object :
from("jsm:queue:<name>").bean("myMessageService", "sendToTCP");
Here the bean code :
public class MessageService {
private Channel openedChannel;
public void sendToTCP(final Exchange exchange) {
// opened channel will use encoders before writing on the socket already
// created in the first route
openedChannel.writeAndFlush(exchange.getIn().getBody());
}
public void receiveFromTCP(final Exchange exchange) {
// record the channel created in the first route.
this.openedChannel = exchange.getProperty(NettyConstants.NETTY_CHANNEL, Channel.class);
}
}
Of course,
the same bean instance is used in the two routes, you need to use a registry to do so :
SimpleRegistry simpleRegistry = new SimpleRegistry();
simpleRegistry.put("myMessageService", new MessageService());
Since the bean is used in two different asynchronous routes, you will have to deal with some unexected situations, by for example protecting the access of openedChannel member, or dealing with unexpected deconnexion.
This post helped me a lot to find this solution :
how-to-send-a-response-back-over-a-established-tcp-connection-in-async-mode-usin
reuseChannel property documentation
After end of camel route, exchange's body and headers will back to requester as response.

Invoking Watson speech-to-text from Java through a corporate proxy

I am using the Watson Java SDK from github (https://github.com/watson-developer-cloud/java-sdk) to run a test of the speech-to-text service. I am running an example from my workplace, which has a firewall and an http proxy set up.
The test fails because the remote server cannot be reached. The stack trace is as follows:
Exception in thread "main" java.lang.RuntimeException: java.net.UnknownHostException: stream.watsonplatform.net
at com.ibm.watson.developer_cloud.service.WatsonService$1.execute(WatsonService.java:182)
at com.costaisa.app.api.test.ibm.watson.TestIBMWatson.testSpeechToText(TestIBMWatson.java:76)
at com.costaisa.app.api.test.ibm.watson.TestIBMWatson.main(TestIBMWatson.java:37)
Caused by: java.net.UnknownHostException: stream.watsonplatform.net
at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:928)
at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1323)
at java.net.InetAddress.getAllByName0(InetAddress.java:1276)
at java.net.InetAddress.getAllByName(InetAddress.java:1192)
at java.net.InetAddress.getAllByName(InetAddress.java:1126)
at okhttp3.Dns$1.lookup(Dns.java:39)
at okhttp3.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:173)
at okhttp3.internal.http.RouteSelector.nextProxy(RouteSelector.java:139)
at okhttp3.internal.http.RouteSelector.next(RouteSelector.java:81)
at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:172)
at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:123)
at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:93)
at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:296)
at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
at okhttp3.RealCall.getResponse(RealCall.java:243)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
at okhttp3.RealCall.execute(RealCall.java:57)
at com.ibm.watson.developer_cloud.service.WatsonService$1.execute(WatsonService.java:179)
... 2 more
It seems to me that okhttp3 supports HTTP proxies but not through environment variables or system properties.
Am I missing something? Is it at all possible to invoke the Watson speech-to-text service from Java through a proxy?
EDIT
I'm no longer working with Watson (not even the same job!), but it became apparent that what I wanted to do was not possible with the then current implementation. A comment to this question (not an answer) provided the actual answer: you cannot do it without changing the implementation. I'd vote that as an answer, but alas it's only a comment. I hope this is useful for other people looking for an answer.
Juanjo this is what you can do to pass the request through corporate proxy.
Create a class that extends from TextToSpeech (as ExtendedTextToSpeech that I wrote for me.).
Then change the DemoServlet that comes with the watson sample as below
TextToSpeech textService = new com.ibm.cloudoe.samples.ExtendedTextToSpeech();
textService.setUsernameAndPassword("username", "password");
String voice = req.getParameter("voice");
String text = req.getParameter("text");
String format = "audio/ogg; codecs=opus";
in = textService.synthesize(text, new Voice(voice, null, null), format);
If you get javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target, then
login to stream.watsonplatform.net/text-to-speech/api/v1 with your username/password received from your watson account's text-to-speech service
Click on the lock sign in the browser's address bar and export the certificate.
Follow the steps here http://magicmonster.com/kb/prg/java/ssl/pkix_path_building_failed.html

activemq - create new broker in servicemix/fuseesb

I'm using fuseesb as my esb and i wanted to create new message broken in activemq, so i'm doing:
in karaf: activemq:create-broker --name=myBroker
then i see:
Creating file: #|green .../myBroker-broker.xml|
Default ActiveMQ Broker (myBroker) configuration file created at: .../myBroker-broker.xml
Please review the configuration and modify to suite your needs.
i see that the file was created, but in karaf i see then:
karaf#root> Exception in thread "SpringOsgiExtenderThread-26" java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext
at org.springframework.context.support.AbstractRefreshableApplicationContext.getBeanFactory(AbstractRefreshableApplicationContext.java:171)
at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext$4.run(AbstractDelegatedExecutionApplicationContext.java:368)
at org.springframework.osgi.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:320)
at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:132)
at java.lang.Thread.run(Thread.java:679)
And i don't know what it is...
Could you help me?
I had the same exception and fixed it by changing the configured ports in my newly-generated broker xml file so they didn't clash with the default broker, which is configured in etc/activemq-broker.xml

EJB, JNDI & ENC - real life scenario

I am preparing for the EJB certification and I am going thro the EJB 3.1 book (O'Reilly)
One of the chapters discusses about JNDI, ENC and the EJB connections
Can some of you give me a real life scenario of these so that I can get a better understandin
JNDI in this scenario is used as a central location through which 'names' (a kind of URL) are routed to an EJB bean. Think of it how a Servlet is mapped to a URL.
If EJB beans are local to an application (e.g. they reside within the web module or within the EJB module of the same EAR), then you don't necessarily need to come into contact with JNDI. Namely, you'd probably use injection to get instances of your bean and no JNDI is needed then.
However, if you need to address an EJB bean in a remote server or if you want to lookup (a proxy to) a bean programmatically, you'd use its JNDI name and JNDI to get hold of it.
See this for some more info, including ENC: Declaring #Resource and #EJB at the class level in Java EE6

Apache Camel: Keeping routing information completely independent of the Java Code

First of all thanks to folks who are currently involved in the development of Camel, I am grateful for all the hard work they have put in.
I am looking for some design advice.
The architecture is something like this:
I have a bunch of Java classes which when instantiated are required to connect to each other and send messages using Apache Camel. The design constraints require me to create a framework such that all routing information, producers, consumers, endpoints etc should be a part of the camel-context.xml.
An individual should have the capability to modify such a file and completely change the existing route without having the Java code available to him.(The Java code would not be provided, only the compiled Jar would be)
For example in One setup,
Bean A ->Bean B->Bean C->file->email.
in another
Bean B->Bean A->Bean C->ftp->file->email
We have tried various approached, but if the originating bean is not implemented as a Java DSL, the messages rate is very high because camel constantly invokes Bean A in the first example and Bean B in the second(they being the source).
Bean A and Bean B originate messages and are event driven. In case the required event occurs, the beans send out a notification message.
My transformations are very simple and I do not require the power of Java DSL at all.
To summarize, I have the following questions:
1) Considering the above constraints, I do I ensure all routing information, including destination addresses, everything is a part of the camel context file?
2) Are there example I can look at for keeping the routing information completely independent of the java code?
3) How do I ensure Camel does not constantly invoke the originating bean?
4) Does Camel constantly invoke just the originating bean or any bean it sends & messages to irrespective of the position of the bean in the entire messaging queue?
I have run out of options trying various ways to set this up. Any help would be appreciated.
Read about hiding the middleware on the Camel wiki pages. This allows you to let clients use an interface to send/receive messages but totally unaware of Camel (no Camel API used at all).
Even better consider buying the Camel in Action book and read chapter 14 which talks about this.
http://www.manning.com/ibsen/
Save 41% on Manning books: Camel in Action or ActiveMQ in Action. Use code s2941. Expires 6th oct. http://www.manning.com/ibsen/
If you consider using ServiceMix of FuseESB, you might want to separate your routes in two parts.
First part would be the Event-driver bean that trigger the route. It could push messages to the ServiceNMR (see http://camel.apache.org/nmr.html).
The other part would be left to the framework users, using Spring DSL. It would just listen to message on the NMR (push by the other route) and do whatever they want with it.
Of course endpoint definition could be propertized using servicemix configuration service (see http://camel.apache.org/properties.html#Properties-UsingBlueprintpropertyplaceholderwithCamelroutes)

Resources