WebSockets work fine in local server but fail when deploy on Pivotal cloud - spring-websocket

It works ok when I deploy on my local server, work fine with any browsers, but when I deploy on Pivotal cloud, it's fail as below console log:
Console.log error:
WebSocket connection to 'wss://bmwbics.apps.pivotal.com/connect/sockjs/735/l8r_friu/websocket' failed: One or more reserved bits are on: reserved1 = 0, reserved2 = 1, reserved3 = 1
Update other developers have issue like me.
I have set up wrong url_prefix to initialize SocketJS.
At this time, I do not what is difference between url_prefix of pivotal and my local.
After that I have updated the way getting url_prefix as code below and it works fine.
Javascript code:
var protocol = location.protocol;
var hostname = location.hostname;
var port = location.port;
var url_prefix = protocol + "//" + hostname + (port === '' ? '' : ':' + port) + contextPath;
var sock = new SockJS(url_prefix + '/connectsocket');
Java configuration code:
#Configuration
#EnableWebSocket
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
private static final int MESSAGE_SIZE_LIMIT = 1024 * 1024;
private static final int SEND_BUFFER_SIZE_LIMIT = 1024 * 1024;
private static final int SEND_TIME_LIMIT = 10 * 10000;
#Override
public final void registerStompEndpoints(final StompEndpointRegistry registry) {
registry.addEndpoint("/connectsocket").withSockJS();
}
#Override
public final void configureMessageBroker(final MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/");
}
#Override
public final void configureWebSocketTransport(final WebSocketTransportRegistration registration) {
registration.setMessageSizeLimit(MESSAGE_SIZE_LIMIT);
registration.setSendBufferSizeLimit(SEND_BUFFER_SIZE_LIMIT);
registration.setSendTimeLimit(SEND_TIME_LIMIT);
}
}

Related

How to add Channel Handler to TCPServer on Channel initialization

I have the following code snipped that creates a TCPServer, and attaches a ChannelHandler to the channel in the doOnChannelInit() function. The server is to process byte data from an embedded device.
#Component
#RequiredArgsConstructor
public class NettyServer {
Logger log = LoggerFactory.getLogger(NettyServer.class);
private final NettyProperties nettyProperties;
private final NettyServerHandler nettyServerHandler;
private TcpServer server;
public void run() {
server = TcpServer
.create()
.host("localhost")
.port(nettyProperties.getTcpPort())
.doOnChannelInit((connectionObserver, channel, remoteAddress) -> {
log.info("Connection from " + remoteAddress);
channel.pipeline()
.addLast("idleStateHandler", new IdleStateHandler(0, 0, 4, TimeUnit.MINUTES))
.addLast(new ByteArrayDecoder())
.addLast(new ByteArrayEncoder())
.addLast(nettyServerHandler);
});
server.bindNow();
log.info("Server running");
}
}
Channel handler
#Component
#RequiredArgsConstructor
#ChannelHandler.Sharable
public class NettyServerHandler extends SimpleChannelInboundHandler<byte[]> {
Logger log = LoggerFactory.getLogger(NettyServerHandler.class);
private final AttributeKey<byte[]> dataKey = AttributeKey.valueOf("dataBuf");
private final AttributeKey<Integer> dataLen = AttributeKey.valueOf("dataBufLen");
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
log.info("New Meter connection from : " + ctx.channel());
}
#Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (ctx.channel() != null) {
log.info(String.format("Meter/Client Disconnected. No: %s ; Channel : %s", meterNo, ctx.channel()));
}
ctx.close();
}
#Override
protected void channelRead0(ChannelHandlerContext ctx, byte[] msg) throws Exception {
log.info("Message received: " + new String(msg);
ctx.channel().read();
}
}
I'm able to connect to the server, but when i send a message, nothing happens, the log statements are not triggered.
I'm not sure what I'm missing here, would appreciate some help.
Thanks
There is no need to add custom handlers to the Netty pipeline. The example above can be written like this:
#Component
#RequiredArgsConstructor
public class NettyServer {
Logger log = LoggerFactory.getLogger(NettyServer.class);
private final NettyProperties nettyProperties;
private TcpServer server;
public void run() {
server = TcpServer
.create()
.host("localhost")
.port(nettyProperties.getTcpPort())
.doOnChannelInit((connectionObserver, channel, remoteAddress) -> {
log.info("Connection from " + remoteAddress);
channel.pipeline()
.addLast("idleStateHandler", new IdleStateHandler(0, 0, 4, TimeUnit.MINUTES));
})
.handle((in, out) ->
in.receive()
.asString()
.doOnNext(s -> log.info("Message received: " + s))
.then());
server.bindNow();
log.info("Server running");
}
}
Consider checking the Reference Documentation
The incoming data can be transformed to String with (asString), to byte[] with (asByteArray) etc. If there is no suitable transformation you can use map(byteBuf -> ...) and transform the ByteBuf to the needed abstraction.

Very slow performance of spring-amqp comsumer

I've been experiencing troubles with spring-boot consumer. I compared the work of two consumers.
First consumer:
import com.rabbitmq.client.*;
import java.io.IOException;
public class Recv {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
Consumer consumer = new DefaultConsumer(channel) {
#Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) throws IOException {
}
};
channel.basicConsume(QUEUE_NAME, true, consumer);
}
}
Second consumer:
#Controller
public class Consumer {
#RabbitListener(queues = "hello")
public void processMessage(Message message) {
}
}
There are no config files for spring-boot consumer installed, everything goes by default.
On my computer first one works 10 times faster. What might be the problem?
The default prefetch (basicQos) for Spring AMQP consumers is 1 which means only 1 message is outstanding at the consumer at any one time; configure the rabbitListenerContainerFactory #Bean to set the prefetchCount to something larger.
You will have to override the default boot-configured #Bean.

Connecting to Open LDAP fails to bind with System.DirectoryServices.Protocols

I have been trying to connect to Open LDAP using sample code from MSDN (Alex Tcherniakhovski)
http://blogs.msdn.com/b/alextch/archive/2012/05/07/sample-code-to-query-openldap-directory-via-net-system-directoryservices-protocols.aspx
I have tried on PORT 636 : ssl as it is in the sample code
And on PORT 389 non ssl to see if i could succeed
When trying on PORT 389 (with the same credentials I could connect to the OPEN LDAP using Softerra LDAP Browser)
I get the following error : The distinguished name contains invalid syntax.
I ran Microsoft Network Monitor and found out that some unwanted characters ââ get added to my Bind request just before my name. These characters never appear in the dotnet solution yet they are part of the request and make it fail.
Do you have an idea of how to get rid of these ?
I would have shown an image but i am not allowed.
My monitor shows BindRequest: Version:3, Name:ââcn=Manager,dc=...
in the dotnet code name is "cn=Manager,dc=.."
Using the code as is with SSL on port 636 lead to the following error : The LDAP server is unavailable.
I get the same error trying to connect with sslbind from Solution DirectoryServices.Protocol downloaded from here.
http://www.microsoft.com/en-us/download/confirmation.aspx?id=18086
Thanks for your help
using System.Collections.Generic;
using System.DirectoryServices.Protocols;
using System.Globalization;
using System.Net;
using System.Security;
namespace OpenLDAPNextUID
{
public class LDAPHelper
{
private readonly LdapConnection ldapConnection;
private readonly string searchBaseDN;
private readonly int pageSize;
public LDAPHelper(
string searchBaseDN,
string hostName,
int portNumber,
AuthType authType,
string connectionAccountName,
SecureString connectionAccountPassword,
int pageSize)
{
var ldapDirectoryIdentifier = new LdapDirectoryIdentifier(
hostName,
portNumber,
true,
false);
var networkCredential = new NetworkCredential(
connectionAccountName,
connectionAccountPassword);
ldapConnection = new LdapConnection(
ldapDirectoryIdentifier,
networkCredential)
{AuthType = authType};
ldapConnection.SessionOptions.ProtocolVersion = 3;
this.searchBaseDN = searchBaseDN;
this.pageSize = pageSize;
}
public IEnumerable<SearchResultEntryCollection> PagedSearch(
string searchFilter,
string[] attributesToLoad)
{
var pagedResults = new List<SearchResultEntryCollection>();
var searchRequest = new SearchRequest
(searchBaseDN,
searchFilter,
SearchScope.Subtree,
attributesToLoad);
var searchOptions = new SearchOptionsControl(SearchOption.DomainScope);
searchRequest.Controls.Add(searchOptions);
var pageResultRequestControl = new PageResultRequestControl(pageSize);
searchRequest.Controls.Add(pageResultRequestControl);
while (true)
{
var searchResponse = (SearchResponse)ldapConnection.SendRequest(searchRequest);
var pageResponse = (PageResultResponseControl)searchResponse.Controls[0];
yield return searchResponse.Entries;
if (pageResponse.Cookie.Length == 0)
break;
pageResultRequestControl.Cookie = pageResponse.Cookie;
}
}
}
}
namespace OpenLDAP
{
class Program
{
static void Main(string[] args)
{
var password = new[]{'P','a','s','s','w','#','r','d'};
var secureString = new SecureString();
foreach (var character in password)
secureString.AppendChar(character);
var baseOfSearch = "dc=fabrikam,dc=com";
var ldapHost = "ubuntu.fabrikam.com";
var ldapPort = 636; //SSL
var ldapPort = 389; //not SSL
var connectAsDN = "cn=admin,dc=fabrikam,dc=com";
var pageSize = 1000;
var openLDAPHelper = new LDAPHelper(
baseOfSearch,
ldapHost,
ldapPort,
AuthType.Basic,
connectAsDN,
secureString,
pageSize);
var searchFilter = "nextUID=*";
var attributesToLoad = new[] {"nextUID"};
var pagedSearchResults = openLDAPHelper.PagedSearch(
searchFilter,
attributesToLoad);
foreach (var searchResultEntryCollection in pagedSearchResults)
foreach (SearchResultEntry searchResultEntry in searchResultEntryCollection)
Console.WriteLine(searchResultEntry.Attributes["nextUID"][0]);
Console.Read();
}
}
}

Which MBeans to use (and how) to programmatically determine memory lows for app (CQ5) deployed inside Weblogic

I have to write a standalone Java app that monitors CQ5, deployed inside Weblogic (especially memory usage).
I was able to connect to the Domain Runtime Server in weblogic, using the class below (as found in the docs).
Now, I want to know which MBeans I need to monitor memory lows, so I can fire an event whenever a certain threshold is being hit.
Can any of you give me some insight? This is a pure JMX / Java question, unrelated to CQ.
I am trying to programmatically recreate what Jconsole already does. But I need it programmatically because I need to talk to an external API in case certain thresholds are being hit.
public class PrintServerState {
private static MBeanServerConnection connection;
private static JMXConnector connector;
private static final ObjectName service;
private static final ObjectName bundleWrite;
static {
try {
service = new ObjectName("com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean");
} catch (MalformedObjectNameException e) {
throw new AssertionError(e.getMessage());
}
}
/*
* Initialize connection to the Domain Runtime MBean Server
*/
public static void initConnection(String hostname, String portString,
String username, String password) throws IOException,
MalformedURLException {
String protocol = "t3";
Integer portInteger = Integer.valueOf(portString);
int port = portInteger.intValue();
String jndiroot = "/jndi/";
String mserver = "weblogic.management.mbeanservers.domainruntime";
JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname,
port, jndiroot + mserver);
Hashtable h = new Hashtable();
h.put(Context.SECURITY_PRINCIPAL, username);
h.put(Context.SECURITY_CREDENTIALS, password);
h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
"weblogic.management.remote");
connector = JMXConnectorFactory.connect(serviceURL, h);
connection = connector.getMBeanServerConnection();
System.out.println("***************** get mbean count ************************* " + connection.getMBeanCount());
Set<ObjectName> mbeans = connection.queryNames(null, null);
for (ObjectName mbeanName : mbeans) {
System.out.println(mbeanName);
}
System.out.println("********************** ---- ***********************");
}
/*
* Print an array of ServerRuntimeMBeans.
* This MBean is the root of the runtime MBean hierarchy, and
* each server in the domain hosts its own instance.
*/
public static ObjectName[] getServerRuntimes() throws Exception {
return (ObjectName[])connection.getAttribute(service,
"ServerRuntimes");
}
/*
* Iterate through ServerRuntimeMBeans and get the name and state
*/
public void printNameAndState() throws Exception {
ObjectName[] serverRT = getServerRuntimes();
System.out.println("got server runtimes");
int length = (int) serverRT.length;
for (int i = 0; i < length; i++) {
String name = (String) connection.getAttribute(serverRT[i],
"Name");
String state = (String) connection.getAttribute(serverRT[i],
"Type");
System.out.println("Server name: " + name + ". Server state: "
+ state);
}
}
public static void main(String[] args) throws Exception {
String hostname = args[0];
String portString = args[1];
String username = args[2];
String password = args[3];
PrintServerState s = new PrintServerState();
System.out.println("hostname " + hostname);
System.out.println("portString " + portString);
System.out.println("username " + username);
System.out.println("password " + password);
initConnection(hostname, portString, username, password);
System.out.println("**************************************************");
s.printNameAndState();
connector.close();
}
}
Would this help -
domainRuntime()
cd('/ServerRuntimes/' + eval('managedServerName') + '/JVMRuntime/' + eval('managedServerName'))
heapFreeCurrentPerOld = str(cmo.getHeapFreePercent())
heapFreeCurrentValOld = str(cmo.getHeapFreeCurrent())

Mbean registered but not found in mbean Server

I have a problem about the mbeans. I have created a simple mbean and I have registered it on the default mBeanServer that is run (Via eclipse or java -jar mbean.jar) and in the same process if I try to fouund the mbean registered with a simple query:
for (ObjectInstance instance : mbs.queryMBeans(ObjectNameMbean, null)) {
System.out.println(instance.toString());
}
the query retuerns my mbean, but if I start another process and try to search this mbean registered the mbeas is not found! why?
The approch is : (Process that is running)
public static void main(String[] args) throws Exception
{
MBeanServer mbeanServer =ManagementFactory.getPlatformMBeanServer();
ObjectName objectName = new ObjectName(ObjectNameMbean);
Simple simple = new Simple (1, 0);
mbeanServer.registerMBean(simple, objectName);
while (true)
{
wait (Is this necessary?)
}
}
So this is the first process that is running (that has the only pourpose to registry the mbean, because there is another process that want to read these informations.
So I start another process to search this mbean but nothing.
I 'm not using jboss but the local Java virtual Machine but my scope is to deploy this simple application in one ejb (autostart) and another ejb will read all informations.
All suggestions are really apprecciated.
This example should be more useful :
Object Hello:
public class Hello implements HelloMBean {
public void sayHello() {
System.out.println("hello, world");
}
public int add(int x, int y) {
return x + y;
}
public String getName() {
return this.name;
}
public int getCacheSize() {
return this.cacheSize;
}
public synchronized void setCacheSize(int size) {
this.cacheSize = size;
System.out.println("Cache size now " + this.cacheSize);
}
private final String name = "Reginald";
private int cacheSize = DEFAULT_CACHE_SIZE;
private static final int DEFAULT_CACHE_SIZE = 200;
}
Interface HelloBean (implemented by Hello)
public interface HelloMBean {
public void sayHello();
public int add(int x, int y);
public String getName();
public int getCacheSize();
public void setCacheSize(int size);
}
Simple Main
import java.lang.management.ManagementFactory;
import java.util.logging.Logger;
import javax.management.MBeanServer;
import javax.management.ObjectName;
public class Main {
static Logger aLog = Logger.getLogger("MBeanTest");
public static void main(String[] args) {
try{
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("ApplicationDomain:type=Hello");
Hello mbean = new Hello();
mbs.registerMBean(mbean, name);
// System.out.println(mbs.getAttribute(name, "Name"));
aLog.info("Waiting forever...");
Thread.sleep(Long.MAX_VALUE);
}
catch(Exception x){
x.printStackTrace();
aLog.info("exception");
}
}
}
So now I have exported this project as jar file and run it as "java -jar helloBean.jar" and by eclipse I have modified the main class to read informations of this read (Example "Name" attribute) by using the same objectname used to registry it .
Main to read :
public static void main(String[] args) {
try{
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("ApplicationDomain:type=Hello");
System.out.println(mbs.getAttribute(name, "Name"));
}
catch(Exception x){
x.printStackTrace();
aLog.info("exception");
}
}
But nothing, the bean is not found.
Project link : here!
Any idea?
I suspect the issue here is that you have multiple MBeanServer instances. You did not mention how you acquired the MBeanServer in each case, but in your second code sample, you are creating a new MBeanServer instance which may not be the same instance that other threads are reading from. (I assume this is all in one JVM...)
If you are using the platform agent, I recommend you acquire the MBeanServer using the ManagementFactory as follows:
MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer() ;
That way, you will always get the same MBeanServer instance.

Resources