Singleton Service in weblogic cluster is registering but not invoking activate method - weblogic

I am implementing a singleton service in a weblogic 12.2.1.2 with EBJ 3.1 in a maven multimodule EAR project.
My singleton service is registering in the cluster.
This is the log from the node where is registered:
<BEA-000189> <The Singleton Service Appscoped_Singleton_Service is now active on this server.>
And this is from other node:
<BEA-003130> <Appscoped_Singleton_Service successfully activated on server iss3.>
The singleton service is implementing the interface weblogic.cluster.singleton.SingletonService but the methods activate and deactivate is not invoked when the nodes starts or shutdown.
I was reading something about versioned EARs and MANIFEST files but not understood this.
I need some help to make methods activate and deactivate be invoked.
This is my class:
import java.io.Serializable;
import javax.inject.Inject;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.test.MyTimerLocal;
import weblogic.cluster.singleton.SingletonService;
public class MySingletonServiceClass implements SingletonService, Serializable, MySingletonServiceInterface {
private static final long serialVersionUID = 3966807367110330202L;
private static final String jndiName = "MySingletonServiceClass";
private int myValue;
#Inject
private MyTimerLocal myTimer;
#Override
public int getMyValue() {
return this.myValue;
}
#Override
public synchronized void setMyValue(final int myValue) {
this.myValue = myValue;
}
#Override
public void activate() {
System.out.println("activate triggered");
Context ic = null;
try {
ic = new InitialContext();
ic.bind(MySingletonServiceClass.jndiName, this);
System.out.println("Object now bound in JNDI at " + MySingletonServiceClass.jndiName);
this.myValue = 5;
final String msg = "###################### MySingletonServiceClass.activate():: Fechamento agendado para " + this.myTimer.agendaExecucao() + " ###############";
System.out.println(msg);
} catch (final NamingException e) {
this.myValue = -1;
e.printStackTrace();
} finally {
try {
if (ic != null) {
ic.close();
}
} catch (final NamingException e) {
e.printStackTrace();
}
}
}
#Override
public void deactivate() {
System.out.println("deactivate triggered");
Context ic = null;
try {
ic = new InitialContext();
ic.unbind(MySingletonServiceClass.jndiName);
System.out.println("Context unbound successfully");
} catch (final NamingException e) {
e.printStackTrace();
}
}
}
Thanks for your time.

I got this working now with this in my src\main\application\META-INF\weblogic-application.xml
<wls:singleton-service>
<wls:class-name>com.test.MySingletonServiceClass</wls:class-name>
<wls:name>Appscoped_Singleton_Service</wls:name>
</wls:singleton-service>

Related

How to run/manage container background thread in Java EE 7+?

Similar to Background Thread for a Tomcat servlet app but I'm looking for a Java EE 7 specific solution.
This is what I finally came up with for WildFly 11 (Java EE 7) without using any configuration changes/additions to beans.xml/web.xml:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.enterprise.concurrent.ManagedThreadFactory;
#Startup
#Singleton
public class IndexingTask implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(IndexingTask.class);
private Thread taskThread = null;
private final CountDownLatch shutdownLatch = new CountDownLatch(1);
#Resource
private ManagedThreadFactory threadFactory;
#PostConstruct
public void postConstruct() {
taskThread = threadFactory.newThread(this);
taskThread.start();
}
#PreDestroy
public void preDestroy(){
shutdownLatch.countDown();
try {
taskThread.join();
} catch (InterruptedException ex) {
LOG.warn("interrupted while waiting for " + taskThread + " to shut down", ex);
}
}
#Override
public void run() {
LOG.info("started");
try {
while (!shutdownLatch.await(100, TimeUnit.MILLISECONDS)) {
}
} catch (InterruptedException ex) {
LOG.warn("", ex);
}
LOG.info("stopped");
}
}
https://javagc.leponceau.org/2017/10/how-to-runmanage-container-background.html
See also Java EE 7 containers: initialize bean at startup without adding it to beans.xml?

Unable to log in to Apache FTP Server

I am trying to integrate the Apache FTP server into my application. I have followed the instructions given here but have run into some problems. Currently I am able to run the server and connect to it from my browser but can not log in. I have tried admin/admin and anonymous/*, but the login fails every time. In the apache-ftpserver-1.0.6 source code I had downloaded, the files associated with the user manager are located in res/conf, although when I try to match that file path in my own program I get an error that says "invalid resource directory name" and am unable to build. I also tried including the files users.properties and ftpd-typical.xml in the main directly and can run, but again cannot log in. It seems like my project does not realize these files are present.
Does anyone have experience with Apache FTP Server that could tell me the correct way to include these files so that I can log in to my server?
Thanks!
P.S. I don't think it should make any difference, but I am developing this program for Android.
In the following code I am crating admin user and non-admin user, setting restrictions of reading, writing and restricting throttling and upload rate limit and imposing download rate limiting.
Added a listener to listen user login and logout download start and download finish events.
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.ftplet.FileSystemFactory;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.Ftplet;
import org.apache.ftpserver.ftplet.UserManager;
import org.apache.ftpserver.ftpletcontainer.impl.DefaultFtpletContainer;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
import org.apache.ftpserver.usermanager.SaltedPasswordEncryptor;
import org.apache.ftpserver.usermanager.impl.BaseUser;
import org.apache.ftpserver.usermanager.impl.ConcurrentLoginPermission;
import org.apache.ftpserver.usermanager.impl.TransferRatePermission;
import org.apache.ftpserver.usermanager.impl.WritePermission;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SFTPServer {
// ===========================================================
// Constants
// ===========================================================
private final int FTP_PORT = 2221;
private final String DEFAULT_LISTENER = "default";
// private final Logger LOG = LoggerFactory.getLogger(SFTPServer.class);
private static final List<Authority> ADMIN_AUTHORITIES;
private static final int BYTES_PER_KB = 1024;
private static final String DEFAULT_USER_DIR = "C:\\upload";
public final static int MAX_CONCURRENT_LOGINS = 1;
public final static int MAX_CONCURRENT_LOGINS_PER_IP = 1;
// ===========================================================
// Fields
// ===========================================================
private static FtpServer mFTPServer;
private static UserManager mUserManager;
private static FtpServerFactory mFTPServerFactory;
private ListenerFactory mListenerFactor;
// ===========================================================
// Constructors
// ===========================================================
static {
// Admin Authorities
ADMIN_AUTHORITIES = new ArrayList<Authority>();
ADMIN_AUTHORITIES.add(new WritePermission());
ADMIN_AUTHORITIES.add(new ConcurrentLoginPermission(MAX_CONCURRENT_LOGINS, MAX_CONCURRENT_LOGINS_PER_IP));
ADMIN_AUTHORITIES.add(new TransferRatePermission(Integer.MAX_VALUE, Integer.MAX_VALUE));
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
public void init() throws FtpException {
mFTPServerFactory = new FtpServerFactory();
mListenerFactor = new ListenerFactory();
mListenerFactor.setPort(FTP_PORT);
mFTPServerFactory.addListener(DEFAULT_LISTENER, mListenerFactor.createListener());
mFTPServerFactory.getFtplets().put(FTPLetImpl.class.getName(), new FTPLetImpl());
PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
userManagerFactory.setFile(new File("ftpusers.properties"));
userManagerFactory.setPasswordEncryptor(new SaltedPasswordEncryptor());
mUserManager = userManagerFactory.createUserManager();
mFTPServerFactory.setUserManager(mUserManager);
this.createAdminUser();
SFTPServer.addUser("admin1", "admin1", 20, 20);
mFTPServer = mFTPServerFactory.createServer();
mFTPServer.start();
}
private UserManager createAdminUser() throws FtpException {
UserManager userManager = mFTPServerFactory.getUserManager();
String adminName = userManager.getAdminName();
if (!userManager.doesExist(adminName)) {
// LOG.info((new
// StringBuilder()).append("Creating user : ").append(adminName).toString());
BaseUser adminUser = new BaseUser();
adminUser.setName(adminName);
adminUser.setPassword(adminName);
adminUser.setEnabled(true);
adminUser.setAuthorities(ADMIN_AUTHORITIES);
adminUser.setHomeDirectory(DEFAULT_USER_DIR);
adminUser.setMaxIdleTime(0);
userManager.save(adminUser);
}
return userManager;
}
public static void addUser(String username, String password, int uploadRateKB, int downloadRateKB) throws FtpException {
BaseUser user = new BaseUser();
user.setName(username);
user.setPassword(password);
user.setHomeDirectory(DEFAULT_USER_DIR);
user.setEnabled(true);
List<Authority> list = new ArrayList<Authority>();
list.add(new TransferRatePermission(downloadRateKB * BYTES_PER_KB, uploadRateKB * BYTES_PER_KB)); // 20KB
list.add(new ConcurrentLoginPermission(MAX_CONCURRENT_LOGINS, MAX_CONCURRENT_LOGINS_PER_IP));
user.setAuthorities(list);
mFTPServerFactory.getUserManager().save(user);
}
public static void restartFTP() throws FtpException {
if (mFTPServer != null) {
mFTPServer.stop();
try {
Thread.sleep(1000 * 3);
} catch (InterruptedException e) {
}
mFTPServer.start();
}
}
public static void stopFTP() throws FtpException {
if (mFTPServer != null) {
mFTPServer.stop();
}
}
public static void pauseFTP() throws FtpException {
if (mFTPServer != null) {
mFTPServer.suspend();
}
}
public static void resumeFTP() throws FtpException {
if (mFTPServer != null) {
mFTPServer.resume();
}
}
public static void main(String... are) {
try {
new SFTPServer().init();
} catch (FtpException e) {
e.printStackTrace();
}
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}
FTPLET Listener
import java.io.IOException;
import org.apache.ftpserver.ftplet.DefaultFtplet;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.FtpRequest;
import org.apache.ftpserver.ftplet.FtpSession;
import org.apache.ftpserver.ftplet.FtpletResult;
public class FTPLetImpl extends DefaultFtplet {
#Override
public FtpletResult onLogin(FtpSession session, FtpRequest request) throws FtpException, IOException {
System.out.println(session.getUser().getName() + " Logged in");
return super.onLogin(session, request);
}
#Override
public FtpletResult onDisconnect(FtpSession session) throws FtpException, IOException {
System.out.println(session.getUser().getName() + " Disconnected");
return super.onDisconnect(session);
}
#Override
public FtpletResult onDownloadStart(FtpSession session, FtpRequest request) throws FtpException, IOException {
System.out.println(session.getUser().getName() + " Started Downloading File " + request.getArgument());
return super.onDownloadStart(session, request);
}
#Override
public FtpletResult onDownloadEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
System.out.println("Finished Downloading " + request.getArgument());
return super.onDownloadEnd(session, request);
}
}

Netty 4.0 channel gets null

The setup
Windows 7 Professionnal
Eclipse Juno
Java jre7
Netty 4.0.0 Beta2
I have a netty server running on another machine. Then I have a program running on my machine, which is made to simulate many clients communicating with the server concurrently. In order to do that, I have a thread pool implemented with java.util.concurrent.ExecutorService . Each client creates a thread and submit it to the ExecutorService. Just before it ends, that thread creates another one with the same code. The submited code does those steps :
connect to server by sending a handshake (netty bootstrap A and channel A)
get the token from the handshake response
connect to server (netty bootstrap B and channel B)
send one request to server
receive the response
close the connection
create another thread with the same code
The problem
I sometimes get a NullPointerException in NettySocketCommunication.sendMessage(), on channel.write(byteBuf) when sending a request to the server.
01728 16:25:23.870 [nioEventLoopGroup-3804-2] ERROR
c.f.s.virtualuser.VirtualUser - java.lang.RuntimeException:
java.lang.NullPointerException at
c.f.s.virtualuser.VirtualUser.processMessageStep(VirtualUser.java:324)
at
c.f.s.virtualuser.VirtualUser.processNextStep(VirtualUser.java:252)
at
c.f.s.virtualuser.VirtualUser.onChannelConnected(VirtualUser.java:395)
at
c.f.s.c.m.handler.ClientSocketBasedHandler.channelActive(ClientSocketBasedHandler.java:95)
at
io.netty.channel.DefaultChannelHandlerContext.invokeChannelActive(DefaultChannelHandlerContext.java:774)
at
io.netty.channel.DefaultChannelHandlerContext.fireChannelActive(DefaultChannelHandlerContext.java:760)
at
io.netty.channel.ChannelStateHandlerAdapter.channelActive(ChannelStateHandlerAdapter.java:58)
at
io.netty.channel.DefaultChannelHandlerContext.invokeChannelActive(DefaultChannelHandlerContext.java:774)
at
io.netty.channel.DefaultChannelHandlerContext.fireChannelActive(DefaultChannelHandlerContext.java:760)
at
io.netty.channel.DefaultChannelPipeline.fireChannelActive(DefaultChannelPipeline.java:884)
at
io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:223)
at
io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:417)
at
io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:365)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:302) at
io.netty.channel.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:110)
at java.lang.Thread.run(Unknown Source)
Caused by:
java.lang.NullPointerException: null at
c.f.s.c.m.NettySocketCommunication.sendMessage(NettySocketCommunication.java:109)
at
c.f.s.virtualuser.VirtualUser.processMessageStep(VirtualUser.java:317)
... 15 common frames omitted
The code
I removed some logging and comments to make the code blocks shorter. I also have the VirtualUser.java class (not shown here) that implements both IVirtualUserCommunication and IVirtualUserMessages interfaces.
[AbstractVirtualUserCommunication.java]
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultLastHttpContent;
import io.netty.handler.codec.http.HttpRequestEncoder;
import io.netty.handler.codec.http.HttpResponseDecoder;
import io.netty.util.CharsetUtil;
import [...].Amf3;
import [...].Properties;
import [...].LogFactory;
import [...].Logger;
import [...].AbstractRequest;
import [...].IRouterMessage;
import [...].RouterMessage;
import [...].FrimaHandshake;
import [...].IVirtualUserCommunication;
public abstract class AbstractVirtualUserCommunication implements IVirtualUserCommunication
{
protected static Logger Log = LogFactory.getInstance().getLogger(AbstractVirtualUserCommunication.class);
protected String CONFIG_APPLICATION = "target.server.application";
protected String application;
protected String CONFIG_VERSION = "target.server.version";
protected String version;
protected String CONFIG_HANDSHAKE_PORT = "netty.handshake.port";
protected final int defaultHandshakePort = 80;
// The following variables are used by both HTTP and SOCKET communication
protected Bootstrap bootstrapHandshake; // Netty bootstrap used only for handshake
protected Channel channelHandshake; // Netty channel used only for handshake
protected String token; // The token received through handshake process
// Host & port are set in the connect() method
protected String host;
protected int port;
protected Bootstrap bootstrap; // Netty bootstrap used for communication
protected Channel channel; // Netty channel used for communication
/** Connect to the server to get the token */
public void sendHandshake(String host)
{
// Get properties, with default values if they are not specified
this.application = Properties.getString(CONFIG_APPLICATION, "snowstorm");
this.version = Properties.getString(CONFIG_VERSION, "0.0.1");
int handshakePort = Properties.getInt(CONFIG_HANDSHAKE_PORT, defaultHandshakePort);
bootstrapHandshake = new Bootstrap();
try
{
bootstrapHandshake.group(new NioEventLoopGroup());
bootstrapHandshake.channel(NioSocketChannel.class);
bootstrapHandshake.handler(new HandShakeInitializer(/* this */));
// Connect and listen on handshake host/port
channelHandshake = bootstrapHandshake.connect(host, handshakePort).sync().channel();
channelHandshake.closeFuture().sync();
}
catch (InterruptedException e)
{
Log.error(e);
}
finally
{
bootstrapHandshake.shutdown();
}
}
/** Method called after completion of the handshake (the token has been set). */
protected abstract void afterHandshake();
/** Connect to the target server for stress test script execution. */
protected void connect(ChannelHandler handler)
{
bootstrap = new Bootstrap();
try
{
// Initialize the pipeline
bootstrap.group(new NioEventLoopGroup());
bootstrap.channel(NioSocketChannel.class);
bootstrap.handler(handler);
// Connect and listen on host/port
channel = bootstrap.connect(host, port).sync().channel();
if (channel == null)
{
Log.error("PROBLEM : The channel is null in the afterHandshake() method");
}
channel.closeFuture().sync();
}
catch (InterruptedException e)
{
Log.error(e);
}
finally
{
bootstrap.shutdown();
}
}
/** Create a RouterMessage with the specified request. */
protected IRouterMessage buildMessage(AbstractRequest request)
{
RouterMessage routerMessage = new RouterMessage();
routerMessage.bytes = Amf3.serialize(request);
routerMessage.token = this.token;
routerMessage.application = this.application;
routerMessage.version = this.version;
return routerMessage;
}
#Override
public void disconnect()
{
// TODO Is it dangerous to not call channel.close() ??
if (channel != null)
{
channel.close().awaitUninterruptibly();
}
else
{
Log.error("PROBLEM : The channel is null when calling the disconnect() method");
}
bootstrap.shutdown();
}
#Override
public boolean isConnected()
{
if (channel == null)
{
return false;
}
return channel.isActive();
}
private class HandShakeInitializer extends ChannelInitializer<SocketChannel>
{
public HandShakeInitializer()
{
super();
}
#Override
protected void initChannel(SocketChannel socketChannel) throws Exception
{
socketChannel.pipeline().addLast("encoder", new HttpRequestEncoder());
socketChannel.pipeline().addLast("decoder", new HttpResponseDecoder());
socketChannel.pipeline().addLast("handler", new HandShakeHandler(/* communication */));
}
}
private class HandShakeHandler extends ChannelInboundMessageHandlerAdapter<Object>
{
public HandShakeHandler()
{
super();
}
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception
{
super.channelActive(ctx);
ctx.write(FrimaHandshake.create(null, version, application));
ctx.flush();
}
#Override
public void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception
{
if (msg instanceof DefaultLastHttpContent)
{
DefaultLastHttpContent defaultLastHttpContent = (DefaultLastHttpContent) msg;
String content = defaultLastHttpContent.data().toString(CharsetUtil.UTF_8);
// Format = token~publicDNS and we only need the token here
token = content;// .split("~")[0];
Log.debug("Starting a bot with token " + token);
afterHandshake();
}
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
{
Log.error(cause);
ctx.close();
}
}
}
[NettySocketCommunication.java]
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import [..­.].AbstractRequest;
import [..­.].IRouterMessage;
import [..­.].Serializer;
import [..­.].ClientSocketBasedHandler;
import [..­.].ClientSocketBasedInitializer;
import [..­.].IVirtualUserMessages;
public class NettySocketCommunication extends AbstractVirtualUserCommunication
{
private ClientSocketBasedHandler handler;
private ChannelFuture testChannelFuture;
public NettySocketCommunication()
{
super();
Log.setLevelToInfo();
this.handler = new ClientSocketBasedHandler();
}
#Override
public void setVirtualUser(IVirtualUserMessages virtualUser)
{
this.handler.setVirtualUser(virtualUser);
}
#Override
public void connect(String host, int port)
{
this.host = host;
this.port = port;
// Get the token from the server through the handshake process
sendHandshake(host);
}
#Override
public boolean connectTest(String host, int port)
{
boolean connectSuccess = false;
bootstrap = new Bootstrap();
// Initialize the pipeline
bootstrap.group(new NioEventLoopGroup());
bootstrap.channel(NioSocketChannel.class);
bootstrap.handler(new ClientSocketBasedInitializer(new ClientSocketBasedHandler()));
// Listen on host/port (connect a channel)
testChannelFuture = bootstrap.connect(host, port);
testChannelFuture.awaitUninterruptibly();
if (testChannelFuture.isSuccess())
{
connectSuccess = true;
}
testChannelFuture.channel().close().awaitUninterruptibly();
bootstrap.shutdown();
return connectSuccess;
}
#Override
protected void afterHandshake()
{
super.connect(new ClientSocketBasedInitializer(handler));
}
#Override
public void sendMessage(AbstractRequest request)
{
IRouterMessage routerMessage = buildMessage(request);
ByteBuf byteBuf = Serializer.encode(routerMessage, true);
// Send message
channel.write(byteBuf);
channel.flush();
}
}
[ClientSocketBasedHandler.java]
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import java.util.ArrayList;
import java.util.List;
import [...].Amf3;
import [...].LogFactory;
import [...].Logger;
import [...].IMessage;
import [...].IRouterMessage;
import [...].IVirtualUserMessages;
public class ClientSocketBasedHandler extends ChannelInboundMessageHandlerAdapter<IRouterMessage>
{
protected static Logger Log = LogFactory.getInstance().getLogger(ClientSocketBasedHandler.class);
private IVirtualUserMessages virtualUser;
public ClientSocketBasedHandler()
{
super();
Log.setLevelToInfo();
}
public void setVirtualUser(IVirtualUserMessages virtualUser)
{
this.virtualUser = virtualUser;
}
#Override
public void messageReceived(ChannelHandlerContext ctx, IRouterMessage routerMessage) throws Exception
{
List<IMessage> messages = deserializeMessages(routerMessage.getBytes());
for (IMessage message : messages)
{
Log.debug("Received socket : " + message);
if (virtualUser == null)
{
throw new RuntimeException("Must call the setVirtualUser() method before receiving messages");
}
virtualUser.onManticoreMessageReceived(message);
}
}
protected List<IMessage> deserializeMessages(byte[] bytes)
{
Object probablyMessages = Amf3.deserialize(bytes);
List<IMessage> messages = null;
// List of Messages
if (probablyMessages instanceof ArrayList)
{
messages = (List<IMessage>) probablyMessages;
}
// Single Message
else if (probablyMessages instanceof IMessage)
{
messages = new ArrayList<IMessage>(1);
messages.add((IMessage) probablyMessages);
}
// Probably Pollution
else
{
Log.error("Cannot deserialize message '{}'", probablyMessages.toString());
}
return messages;
}
#Override
public void channelActive(ChannelHandlerContext ctx)
{
if (virtualUser != null)
{
virtualUser.onChannelConnected();
}
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
{
Log.error(cause);
ctx.close();
}
}
The search
I looked at netty channels related questions on stack overflow, but couldn't find anything relevant to my case.
Links
http://netty.io/4.0/api/io/netty/channel/Channel.html
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html

Jackson2 custom deserializer factory

I am porting jackson 1.6 code to jackson 2 and stumbled upon a deprecated code.
What i did in jackson 1.6 is:
CustomDeserializerFactory sf = new CustomDeserializerFactory();
mapper.setDeserializerProvider(new StdDeserializerProvider(sf));
sf.addSpecificMapping(BigDecimal.class, new BigDecimalDeserializer());
t = mapper.readValue(ts, X[].class);
Anyone knows how to do it in jackson 2?
To add a factory--not just a deserializer--don't use SimpleModule. Create your own Module and within it create a Deserializers object that is added to the SetUpContext. The Deserializers object will have access to similar methods that the factory did where you can get extra type information about the deserializer needed.
It will look something like this (note that it doesn't need to be an inner class):
public class MyCustomCollectionModule extends Module {
#Override
public void setupModule(final SetupContext context) {
context.addDeserializers(new MyCustomCollectionDeserializers());
}
private static class MyCustomCollectionDeserializers implements Deserializers {
...
#Override
public JsonDeserializer<?> findCollectionDeserializer(final CollectionType type, final DeserializationConfig config, final BeanDescription beanDesc, final TypeDeserializer elementTypeDeserializer, final JsonDeserializer<?> elementDeserializer) throws JsonMappingException {
if (MyCustomCollection.class.equals(type.getRawClass())) {
return new MyCustomCollectionDeserializer(type);
}
return null;
}
...
}
}
In Jackson 2.0:
Create a Module (usually SimpleModule)
Register custom handlers with it.
Call ObjectMapper.registerModule(module);.
This is available on Jackson 1.x as well (since 1.8 or so).
Here is an example of registering a module (in this case Joda date handling) in Jackson 2.x:
ClientConfig clientConfig = new DefaultClientConfig();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
JacksonJsonProvider provider = new JacksonJsonProvider();
provider.configure(SerializationFeature.INDENT_OUTPUT, true);
provider.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
provider.setMapper(mapper);
clientConfig.getSingletons().add(provider);
Client client = Client.create(clientConfig);
Exemplifying #StaxMan answer
Basically you need to create a module (SimpleModule), add a deserializer and register this module
final SimpleModule sm = new SimpleModule();
sm.addDeserializer(Date.class, new JsonDeserializer<Date>(){
#Override
public Date deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException {
try {
System.out.println("from my custom deserializer!!!!!!");
return new SimpleDateFormat("yyyy-MM-dd").parse(p.getValueAsString());
} catch (ParseException e) {
System.err.println("aw, it fails: " + e.getMessage());
throw new IOException(e.getMessage());
}
}
});
final CreationBean bean = JsonUtils.getMapper()
.registerModule(sm)
// .setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
.readValue("{\"dateCreation\": \"1995-07-19\"}", CreationBean.class);
Here a fully example
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
/**
* #author elvis
* #version $Revision: $<br/>
* $Id: $
* #since 8/22/16 8:38 PM
*/
public class JackCustomDeserializer {
public static void main(String[] args) throws IOException {
final SimpleModule sm = new SimpleModule();
sm.addDeserializer(Date.class, new JsonDeserializer<Date>(){
#Override
public Date deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException {
try {
System.out.println("from my custom deserializer!!!!!!");
return new SimpleDateFormat("yyyy-MM-dd").parse(p.getValueAsString());
} catch (ParseException e) {
System.err.println("aw, it fails: " + e.getMessage());
throw new IOException(e.getMessage());
}
}
});
final CreationBean bean = JsonUtils.getMapper()
.registerModule(sm)
// .setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
.readValue("{\"dateCreation\": \"1995-07-19\"}", CreationBean.class);
System.out.println("parsed bean: " + bean.dateCreation);
}
static class CreationBean {
public Date dateCreation;
}
}

USB/Serial communication with Netty

In our organisation, we implemented our own protocol over UDP and TCP to let external devices connected to the Internet exchange messages with a server that we developed using Netty (indeed!).
For testing purpose, we would like to connect those devices directly to our computers through USB/serial interface (we did not choose the serial communication library yet). We would also like to deploy/port the embedded software we developed for our devices on our computer to simulate the devices and to connect directly to our server using a named pipe for example (IPC).
In the Architecture Overview documentation of Netty, you claim that we could use Netty as well for such serial communication:
"Also, you are even able to take advantage of new transports which aren't yet written (such as serial port communication transport), again by replacing just a couple lines of constructor calls. Moreover, you can write your own transport by extending the core API."
Is anyone somewhere already developed such implementation in Netty or does someone else plan to do such implementation? I am also wondering if Netty is really well-suited for that since the Channel interface and many other ones use a SocketAddress to bind/connect to a peer?
Thank you for your suggestions, advices!
I wonder if you may be able to use the new iostream package for that. All you need here is an InputStream and Outputstream. See [1]
[1] https://github.com/netty/netty/tree/master/transport/src/main/java/io/netty/channel/iostream
It is possible to implement such a solutions. I have not meet problems with binding with SocketAddress.
I’m posting my implementation of USB connection with Netty.
Serial communication is quite simillar, I'm not posting it for brevity. However I am happy to add it as well if anyone needs it.
Here is base class for connection. A ChannelHandler shall be implemented according to communication needs.
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import java.net.SocketAddress;
public abstract class ConnectorImpl {
protected ChannelHandler handler;
protected Bootstrap bootstrap;
protected ChannelFuture channelFuture;
public ChannelFuture connect() throws Exception {
if (!isConnected()) {
channelFuture = bootstrap.connect(getSocketAddress()).sync();
}
return channelFuture.channel().closeFuture();
}
public boolean isConnected() {
try {
return channelFuture.channel().isOpen();
} catch (NullPointerException ex) {
return false;
}
}
public void close() {
if (!isConnected()) {
return;
}
try {
channelFuture.channel().close().sync();
} catch (InterruptedException e) {
}
}
protected ChannelOutboundHandlerAdapter createOutgoingErrorHandler() {
return new ChannelOutboundHandlerAdapter() {
#Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
final ChannelFutureListener channelFutureListener = future -> {
if (!future.isSuccess()) {
future.channel().close();
}
};
promise.addListener(channelFutureListener);
ctx.write(msg, promise);
}
};
}
public abstract SocketAddress getSocketAddress();
}
An extensions of that connector for needed type of connection together with Channel implementations is needed.
USB connector:
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.handler.timeout.ReadTimeoutHandler;
import javax.usb.UsbDevice;
import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;
public class UsbConnectorImpl extends ConnectorImpl {
private static final int READ_TIMEOUT = 60;
private final UsbDevice usbDevice;
public UsbConnectorImpl(UsbChannelHandler handler, UsbDevice usbDevice) {
this.handler = handler;
this.usbDevice = usbDevice;
this.bootstrap = new Bootstrap()
.channel(getChannelClass())
.group(getLoop())
.handler(getChannelInitializer());
}
public EventLoopGroup getLoop() {
return new NioEventLoopGroup(1);
}
Class<UsbAsyncChannel> getChannelClass() {
return UsbAsyncChannel.class;
}
ChannelInitializer<Channel> getChannelInitializer() {
return new ChannelInitializer<Channel>() {
#Override
public void initChannel(#SuppressWarnings("NullableProblems") Channel ch) {
ch.pipeline()
.addLast("Generic encoder", new RequestEncoder())
.addLast("Decoder", new ResponseDecoder())
.addLast("Read timeout handler", new ReadTimeoutHandler(READ_TIMEOUT, TimeUnit.SECONDS))
.addLast("Outgoing Error Handler", createOutgoingErrorHandler())
.addLast("Card Reader handler", handler);
}
};
}
public SocketAddress getSocketAddress() {
return new UsbDeviceAddress(usbDevice);
}
}
USB Channel:
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.FileRegion;
import io.netty.channel.nio.AbstractNioByteChannel;
import org.usb4java.LibUsb;
import javax.usb.UsbConfiguration;
import javax.usb.UsbDevice;
import javax.usb.UsbEndpoint;
import javax.usb.UsbInterface;
import javax.usb.UsbPipe;
import javax.usb.event.UsbPipeDataEvent;
import javax.usb.event.UsbPipeErrorEvent;
import javax.usb.event.UsbPipeListener;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.channels.Pipe;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class UsbChannel extends AbstractNioByteChannel {
protected static final byte INTERFACE_BULK_PIPES = (byte) 1;
private static final AtomicInteger READ_TASK_COUNTER = new AtomicInteger();
private final UsbChannelConfig config;
protected UsbPipe outPipe = null;
protected UsbPipe inPipe = null;
private UsbDevice usbDevice;
private UsbDeviceAddress deviceAddress;
private UsbInterface usbInterface;
public UsbChannel() throws IOException {
super(null, Pipe.open().source());
config = new UsbChannelConfig(this);
}
#Override
public UsbChannelConfig config() {
return config;
}
#Override
public boolean isActive() {
return usbDevice != null;
}
#Override
protected ChannelFuture shutdownInput() {
try {
doClose();
} catch (Exception e) {
pipeline().fireExceptionCaught(e);
}
return null;
}
protected abstract ReadTask createReadTask();
protected void invokeRead() {
ReadTask task = createReadTask();
task.scheduledFuture = eventLoop().schedule(task, 0, TimeUnit.MILLISECONDS);
}
#Override
protected AbstractNioUnsafe newUnsafe() {
return new UsbUnsafe();
}
#Override
protected long doWriteFileRegion(FileRegion region) throws Exception {
throw new UnsupportedOperationException();
}
#Override
protected int doReadBytes(ByteBuf buf) throws Exception {
return 0;
}
#Override
protected Pipe.SourceChannel javaChannel() {
return (Pipe.SourceChannel) super.javaChannel();
}
#Override
protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
UsbDeviceAddress remote = (UsbDeviceAddress) remoteAddress;
usbDevice = remote.value();
UsbConfiguration configuration = usbDevice.getActiveUsbConfiguration();
usbInterface = configuration.getUsbInterface(INTERFACE_BULK_PIPES);
usbInterface = usbInterface.getActiveSetting();
usbInterface.claim();
for (int i = 0; i < usbInterface.getUsbEndpoints().size(); i++) {
UsbEndpoint endpoint = (UsbEndpoint) usbInterface.getUsbEndpoints().get(i);
UsbPipe usbPipe = endpoint.getUsbPipe();
if (endpoint.getDirection() == LibUsb.ENDPOINT_IN) {
inPipe = usbPipe;
inPipe.open();
} else if (endpoint.getDirection() == LibUsb.ENDPOINT_OUT) {
outPipe = usbPipe;
outPipe.open();
}
if (inPipe != null && outPipe != null) {
break;
}
}
outPipe.addUsbPipeListener(new UsbPipeListener() {
#Override
public void errorEventOccurred(UsbPipeErrorEvent event) {
pipeline().fireExceptionCaught(event.getUsbException());
}
#Override
public void dataEventOccurred(UsbPipeDataEvent event) {
invokeRead();
}
});
inPipe.addUsbPipeListener(new UsbPipeListener() {
#Override
public void errorEventOccurred(UsbPipeErrorEvent event) {
pipeline().fireExceptionCaught(event.getUsbException());
}
#Override
public void dataEventOccurred(UsbPipeDataEvent event) {
pipeline().fireChannelRead(Unpooled.wrappedBuffer(event.getData(), 0, event.getData().length));
}
});
deviceAddress = remote;
return true;
}
#Override
protected void doFinishConnect() throws Exception {
}
#Override
public UsbDeviceAddress localAddress() {
return (UsbDeviceAddress) super.localAddress();
}
#Override
public UsbDeviceAddress remoteAddress() {
return (UsbDeviceAddress) super.remoteAddress();
}
#Override
protected UsbDeviceAddress localAddress0() {
return deviceAddress;
}
#Override
protected UsbDeviceAddress remoteAddress0() {
return deviceAddress;
}
#Override
protected void doBind(SocketAddress localAddress) throws Exception {
throw new UnsupportedOperationException();
}
#Override
protected void doDisconnect() throws Exception {
doClose();
}
#Override
protected void doClose() throws Exception {
try {
super.doClose();
javaChannel().close();
} finally {
if (inPipe != null) {
inPipe.close();
inPipe = null;
}
if (outPipe != null) {
outPipe.close();
outPipe = null;
}
if (usbInterface != null) {
usbInterface.release();
usbInterface = null;
}
if (usbDevice != null) {
usbDevice = null;
}
}
}
protected abstract static class ReadTask implements Runnable, ChannelFutureListener {
protected final int id;
protected ScheduledFuture<?> scheduledFuture;
public ReadTask() {
this.id = READ_TASK_COUNTER.incrementAndGet();
}
}
private final class UsbUnsafe extends AbstractNioUnsafe {
#Override
public void read() {
}
}
}