Cometd : It seems that ServerChannel lose some subscribers - cometd

I used cometd to realize notification push, but i found out the following issue :
After log in the system, at the beginning, the client can receive message from server, but after wait pretty long time or do some other operation, the client may not receive message from server any more. Did anyone else encountered this problem? Thanks in Advance.
Blow is my code :
1. Client Code
var cometd = dojox.cometd;cometd.websocketEnabled = false;
cometd.init(url);
cometd.subscribe("/foo/new", function(message) {
......The business logic......
}
);
2. The ServletContextAttributeListener that integrate with AbstractService
public class BayeuxInitializerListener implements ServletContextAttributeListener {
private static final String CLIENT_CHANNEL = "/foo/new";
#Override
public void attributeAdded(ServletContextAttributeEvent event) {
if(BayeuxServer.ATTRIBUTE.equals(event.getName())) {
BayeuxServer bayeuxServer = (BayeuxServer) event.getValue();
boolean isCreated = bayeuxServer.createIfAbsent(CLIENT_CHANNEL, new ConfigurableServerChannel.Initializer() {
#Override
public void configureChannel(ConfigurableServerChannel channel) {
channel.setPersistent(true);
}
});
new MyService(bayeuxServer);
}
}
3. Service
public class MyService extends AbstractService {
private static final Logger logger = Logger.getLogger(MyService .class);
private static final String CLIENT_CHANNEL = "/foo/new";
private static final String LISTENER_CHANNEL = "/service/notification";
public MyService(BayeuxServer bayeuxServer) {
super(bayeuxServer, "notification");
this.addService(LISTENER_CHANNEL, "processNotification");
}
public void processNotification(ServerSession serverSession, Map<String, Object> data) {
LocalSession localSession = this.getLocalSession();
if(logger.isDebugEnabled()) {
logger.debug("Local Session : " + localSession.getId() + ".");
}
ServerChannel serverChannel = this.getBayeux().getChannel(CLIENT_CHANNEL)
Set<ServerSession> subscribers = serverChannel.getSubscribers();
if(0 == subscribers.size()) {
logger.info("There are no subcribers for " + CLIENT_CHANNEL + ".");
}
for(ServerSession subscriber : subscribers) {
logger.info("The subscriber for " + CLIENT_CHANNEL + " : " + subscriber.getId() + ".");
}
serverChannel.publish(localSession, data, null);
}

Related

Wrong client and server UDP connection in Java

I must to do chat server for my subject.
Where is my problem ?
I need to write UDP server class which should send and receive messages from users and transfer it to GUI
Second server should have methods for collect public keys of any user, changing owns ect. Additionally he should store this these keys
What do I have?
I have some code from first server, two Threads for sending and receiving messages and some code in client , but it isn't synchronized. And I don't know how to do it
This is some code from client main method: tfServer --> text field for getting this from user
InetAddress ia = InetAddress.getByName(tfServer.getText());
SenderThread sender = new SenderThread(ia,Integer.valueOf(tfPort.getText()));
sender.start();
ReceiverThread receiver = new ReceiverThread(sender.getSocket());
receiver.start();
First server code :
import java.net.* ;
public class Server {
int port;
private final static int PACKETSIZE = 100 ;
private boolean isStopped = false;
public Server(){
}
public Server(int port) {
this.port = port;
}
public void stop() {
this.isStopped = true;
}
public void start() {
try
{
DatagramSocket socket = new DatagramSocket(this.port) ;
System.out.println( "Serwer gotowy..." ) ;
if(!this.isStopped){
for( ;; ){
DatagramPacket packet = new DatagramPacket( new byte[PACKETSIZE], PACKETSIZE ) ;
socket.receive( packet ) ;
System.out.println( packet.getAddress() + " " + packet.getPort() + ": " + new String(packet.getData()) ) ;
socket.send( packet ) ;
}
}
}
catch( Exception e )
{
System.out.println( e ) ;
}
}
}
And class from first server to receive :
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ReceiverThread extends Thread {
private DatagramSocket udpClientSocket;
private boolean stopped = false;
public ReceiverThread(DatagramSocket ds) throws SocketException {
this.udpClientSocket = ds;
}
public void halt() {
this.stopped = true;
}
public void run() {
byte[] receiveData = new byte[1024];
while (true) {
if (stopped)
return;
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
try {
udpClientSocket.receive(receivePacket);
String serverReply = new String(receivePacket.getData(), 0, receivePacket.getLength());
System.out.println("UDPClient: Response from Server: \"" + serverReply + "\"\n");
Thread.yield();
}
catch (IOException ex) {
System.err.println(ex);
}
}
}
}
Second class from first server to send messages :
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ReceiverThread extends Thread {
private DatagramSocket udpClientSocket;
private boolean stopped = false;
public ReceiverThread(DatagramSocket ds) throws SocketException {
this.udpClientSocket = ds;
}
public void halt() {
this.stopped = true;
}
public void run() {
byte[] receiveData = new byte[1024];
while (true) {
if (stopped)
return;
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
try {
udpClientSocket.receive(receivePacket);
String serverReply = new String(receivePacket.getData(), 0, receivePacket.getLength());
System.out.println("UDPClient: Response from Server: \"" + serverReply + "\"\n");
Thread.yield();
}
catch (IOException ex) {
System.err.println(ex);
}
}
}
}
And server PKI :
public class ServerPKI {
}

netty SimpleChannelInboundHandler<String> channelRead0 only occasionally invoked

I know that there are several similar questions that have either been answered or still outstanding, however, for the life of me...
Later Edit 2016-08-25 10:05 CST - Actually, I asked the wrong question.
The question is the following: given that I have both a netty server (taken from DiscardServer example) and a netty client - (see above) what must I do to force the DiscardServer to immediately send the client a request?
I have added an OutboundHandler to the server and to the client.
After looking at both the DiscardServer and PingPongServer examples, there is an external event occurring to kick off all the action. In the case of Discard server, it is originally waiting for a telnet connection, then will transmit whatever was in the telnet msg to the client.
In the case of PingPongServer, the SERVER is waiting on the client to initiate action.
What I want is for the Server to immediately start transmitting after connection with the client. None of the examples from netty seem to do this.
If I have missed something, and someone can point it out, much good karma.
My client:
public final class P4Listener {
static final Logger LOG;
static final String HOST;
static final int PORT;
static final Boolean SSL = Boolean.FALSE;
public static Dto DTO;
static {
LOG = LoggerFactory.getLogger(P4Listener.class);
HOST = P4ListenerProperties.getP4ServerAddress();
PORT = Integer.valueOf(P4ListenerProperties.getListenerPort());
DTO = new Dto();
}
public static String getId() { return DTO.getId(); }
public static void main(String[] args) throws Exception {
final SslContext sslCtx;
if (SSL) {
LOG.info("{} creating SslContext", getId());
sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
} else {
sslCtx = null;
}
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group).channel(NioSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.handler(new P4ListenerInitializer(sslCtx));
// Start the connection attempt.
LOG.debug(" {} starting connection attempt...", getId());
Channel ch = b.connect(HOST, PORT).sync().channel();
// ChannelFuture localWriteFuture = ch.writeAndFlush("ready\n");
// localWriteFuture.sync();
} finally {
group.shutdownGracefully();
}
}
}
public class P4ListenerHandler extends SimpleChannelInboundHandler<String> {
static final Logger LOG = LoggerFactory.getLogger(P4ListenerHandler.class);
static final DateTimeFormatter DTFormatter = DateTimeFormatter.ofPattern("yyyyMMdd-HHMMss.SSS");
static final String EndSOT;
static final String StartSOT;
static final String EOL = "\n";
static final ClassPathXmlApplicationContext AppContext;
static {
EndSOT = P4ListenerProperties.getEndSOT();
StartSOT = P4ListenerProperties.getStartSOT();
AppContext = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml" });
}
private final RequestValidator rv = new RequestValidator();
private JAXBContext jaxbContext = null;
private Unmarshaller jaxbUnmarshaller = null;
private boolean initialized = false;
private Dto dto;
public P4ListenerHandler() {
dto = new Dto();
}
public Dto getDto() { return dto; }
public String getId() { return getDto().getId(); }
Message convertXmlToMessage(String xml) {
if (xml == null)
throw new IllegalArgumentException("xml message is null!");
try {
jaxbContext = JAXBContext.newInstance(p4.model.xml.request.Message.class, p4.model.xml.request.Header.class,
p4.model.xml.request.Claims.class, p4.model.xml.request.Insurance.class,
p4.model.xml.request.Body.class, p4.model.xml.request.Prescriber.class,
p4.model.xml.request.PriorAuthorization.class,
p4.model.xml.request.PriorAuthorizationSupportingDocumentation.class);
jaxbUnmarshaller = jaxbContext.createUnmarshaller();
StringReader strReader = new StringReader(xml);
Message m = (Message) jaxbUnmarshaller.unmarshal(strReader);
return m;
} catch (JAXBException jaxbe) {
String error = StacktraceUtil.getCustomStackTrace(jaxbe);
LOG.error(error);
throw new P4XMLUnmarshalException("Problems when attempting to unmarshal transmission string: \n" + xml,
jaxbe);
}
}
#Override
public void channelActive(ChannelHandlerContext ctx) {
LOG.debug("{} let server know we are ready", getId());
ctx.writeAndFlush("Ready...\n");
}
/**
* Important - this method will be renamed to
* <code><b>messageReceived(ChannelHandlerContext, I)</b></code> in netty 5.0
*
* #param ctx
* #param msg
*/
#Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
ChannelFuture lastWriteFuture = null;
LOG.debug("{} -- received message: {}", getId(), msg);
Channel channel = ctx.channel();
Message m = null;
try {
if (msg instanceof String && msg.length() > 0) {
m = convertXmlToMessage(msg);
m.setMessageStr(msg);
dto.setRequestMsg(m);
LOG.info("{}: received TIMESTAMP: {}", dto.getId(), LocalDateTime.now().format(DTFormatter));
LOG.debug("{}: received from server: {}", dto.getId(), msg);
/*
* theoretically we have a complete P4(XML) request
*/
final List<RequestFieldError> errorList = rv.validateMessage(m);
if (!errorList.isEmpty()) {
for (RequestFieldError fe : errorList) {
lastWriteFuture = channel.writeAndFlush(fe.toString().concat(EOL));
}
}
/*
* Create DBHandler with message, messageStr, clientIp to get
* dbResponse
*/
InetSocketAddress socketAddress = (InetSocketAddress) channel.remoteAddress();
InetAddress inetaddress = socketAddress.getAddress();
String clientIp = inetaddress.getHostAddress();
/*
* I know - bad form to ask the ApplicationContext for the
* bean... BUT ...lack of time turns angels into demons
*/
final P4DbRequestHandler dbHandler = (P4DbRequestHandler) AppContext.getBean("dbRequestHandler");
// must set the requestDTO for the dbHandler!
dbHandler.setClientIp(clientIp);
dbHandler.setRequestDTO(dto);
//
// build database request and receive response (string)
String dbResponse = dbHandler.submitDbRequest();
/*
* create ResponseHandler and get back response string
*/
P4ResponseHandler responseHandler = new P4ResponseHandler(dto, dbHandler);
String responseStr = responseHandler.decodeDbServiceResponse(dbResponse);
/*
* write response string to output and repeat exercise
*/
LOG.debug("{} -- response to be written back to server:\n {}", dto.getId(), responseStr);
lastWriteFuture = channel.writeAndFlush(responseStr.concat(EOL));
//
LOG.info("{}: response sent TIMESTAMP: {}", dto.getId(), LocalDateTime.now().format(DTFormatter));
} else {
throw new P4EventException(dto.getId() + " -- Message received is not a String");
}
processWriteFutures(lastWriteFuture);
} catch (Throwable t) {
String tError = StacktraceUtil.getCustomStackTrace(t);
LOG.error(tError);
} finally {
if (lastWriteFuture != null) {
lastWriteFuture.sync();
}
}
}
private void processWriteFutures(ChannelFuture writeFuture) throws InterruptedException {
// Wait until all messages are flushed before closing the channel.
if (writeFuture != null) {
writeFuture.sync();
}
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
/**
* Creates a newly configured {#link ChannelPipeline} for a new channel.
*/
public class P4ListenerInitializer extends ChannelInitializer<SocketChannel> {
private static final StringDecoder DECODER = new StringDecoder();
private static final StringEncoder ENCODER = new StringEncoder();
private final SslContext sslCtx;
public P4ListenerInitializer(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
#Override
public void initChannel(SocketChannel ch) {
P4ListenerHandler lh = null;
ChannelPipeline pipeline = ch.pipeline();
if (sslCtx != null) {
P4Listener.LOG.info("{} -- constructing SslContext new handler ", P4Listener.getId());
pipeline.addLast(sslCtx.newHandler(ch.alloc(), P4Listener.HOST, P4Listener.PORT));
} else {
P4Listener.LOG.info("{} -- SslContext null; bypassing adding sslCtx.newHandler(ch.alloc(), P4Listener.HOST, P4Listener.PORT) ", P4Listener.getId());
}
// Add the text line codec combination first,
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast(DECODER);
P4Listener.LOG.debug("{} -- added Decoder ", P4Listener.getId());
pipeline.addLast(ENCODER);
P4Listener.LOG.debug("{} -- added Encoder ", P4Listener.getId());
// and then business logic.
pipeline.addLast(lh = new P4ListenerHandler());
P4Listener.LOG.debug("{} -- added P4ListenerHandler: {} ", P4Listener.getId(), lh.getClass().getSimpleName());
}
}
#Sharable
public class P4ListenerOutboundHandler extends ChannelOutboundHandlerAdapter {
static final Logger LOG = LoggerFactory.getLogger(P4ListenerOutboundHandler.class);
private Dto outBoundDTO = new Dto();
public String getId() {return this.outBoundDTO.getId(); }
#Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
try {
ChannelFuture lastWrite = ctx.write(Unpooled.copiedBuffer((String) msg, CharsetUtil.UTF_8));
try {
if (lastWrite != null) {
lastWrite.sync();
promise.setSuccess();
}
} catch (InterruptedException e) {
promise.setFailure(e);
e.printStackTrace();
}
} finally {
ReferenceCountUtil.release(msg);
}
}
}
output from client
Just override channelActive(...) on the handler of the server and trigger a write there.

Spring Integration / Spring cloud Stream : How to send a single message using #inboundchanneladapter

I have the following piece of code :
#Bean
#InboundChannelAdapter(value = Source.OUTPUT, poller = #Poller(fixedDelay = "${fixedDelay}", maxMessagesPerPoll = "1"))
public MessageSource<String> timerMessageSource() {
logger.info("Sending Message");
return () -> new GenericMessage<>(new SimpleDateFormat().format(new Date()));
}
I wish to disable the poller so that i can send a single message out. How do i do that?
That wouldn't make this application a stream :-) You might just write a task that sends a single message out.
Code:
public interface MessageChannels {
#Output("activationMsgQueue")
MessageChannel save();
}
Code:
#Service
#EnableBinding(MessageChannels.class)
public class CloudStreamProducer implements MessageSender {
private static final Logger LOGGER = LoggerFactory
.getLogger(CloudStreamProducer.class);
#Autowired
MessageChannels msgChannel;
public void sendMessage(ActivationDataInfo msg) {
msgChannel.save().send(MessageBuilder.withPayload(msg).build());
LOGGER.info("Sent Activation Message to apt Topic : Acct NO = " + msg.getAcctNo()
+ " TN = " + msg.getTn() + " FlowType = " + msg.getFlowType());
}
}

Extracting CD tagged tokens using UIMA

I wrote an annotator that extracts all CD tagged tokens and the code looks like this
public class WeightAnnotator extends JCasAnnotator_ImplBase {
private Logger logger = Logger.getLogger(getClass().getName());
public static List<Token> weightTokens = new ArrayList<Token>();
public static final String PARAM_STRING = "stringParam";
#ConfigurationParameter(name = PARAM_STRING)
private String stringParam;
#Override
public void initialize(UimaContext context) throws ResourceInitializationException {
super.initialize(context);
}
#Override
public void process(JCas jCas) throws AnalysisEngineProcessException {
logger.info("Starting processing.");
for (Sentence sentence : JCasUtil.select(jCas, Sentence.class)) {
List<Token> tokens = JCasUtil.selectCovered(jCas, Token.class, sentence);
for (Token token : tokens) {
int begin = token.getBegin();
int end = token.getEnd();
if (token.getPos().equals( PARAM_STRING)) {
WeightAnnotation ann = new WeightAnnotation(jCas, begin, end);
ann.addToIndexes();
System.out.println("Token: " + token.getCoveredText());
}
}
}
}
}
but when I am trying to create an iterator on it in a pipeline, the iterator is returning null. Here is how my pipeline looks.
AnalysisEngineDescription weightDescriptor = AnalysisEngineFactory.createEngineDescription(WeightAnnotator.class,
WeightAnnotator.PARAM_STRING, "CD"
);
AggregateBuilder builder = new AggregateBuilder();
builder.add(sentenceDetectorDescription);
builder.add(tokenDescriptor);
builder.add(posDescriptor);
builder.add(weightDescriptor);
builder.add(writer);
for (JCas jcas : SimplePipeline.iteratePipeline(reader, builder.createAggregateDescription())) {
Iterator iterator1 = JCasUtil.iterator(jcas, WeightAnnotation.class);
while (iterator1.hasNext()) {
WeightAnnotation weights = (WeightAnnotation) iterator1.next();
logger.info("Token: " + weights.getCoveredText());
}
}
I generated WeightAnnotator and WeightAnnotator_Type using JCasGen. I debugged the entire code but I don't understand where I am getting this wrong. Any ideas on how to improve this are appreciated.

Netbeans QuickSearch Result to Lookup

Well, I'd like to provide QuickSearch result inside application, and, of course, through the lookup.
Searching works well, but found result is not visible through global lookup.
Can someone help to overcome this issue ?
Here is th code for a quicksearch :
public class QSERSCompany implements SearchProvider {
#Override
public void evaluate(SearchRequest request, SearchResponse response) {
try {
for (Company k : queries.ERSQuery.allCompanies()) {
if (k.getCompanyName().toLowerCase().contains(request.getText().toLowerCase())) {
if (!response.addResult(new SearchResult(k), k.getCompanyName())) {
return;
}
}
}
} catch (NullPointerException npe) {
}
}
private static class SearchResult implements Runnable, Lookup.Provider {
private final Company company;
private final InstanceContent ic = new InstanceContent();
private final Lookup lookup = new AbstractLookup(ic);
public SearchResult(Company c) {
this.company= c;
}
#Override
public void run() {
ic.add(company);
try {
StatusDisplayer.getDefault().setStatusText(
company.getCompanyName()
+ ", " + company.getAddress()
+ ", " + company.getCity());
} catch (NullPointerException npe) {
}
}
#Override
public Lookup getLookup() {
return lookup;
}
}
}
And this is partof the code which listens for a Company object :
public final class ManagementPodatakaTopComponent extends TopComponent {
private Lookup.Result<Company> companyLookup = null;
...
private Company selectedCompany;
...
#Override
public void componentOpened() {
companyLookup = Utilities.actionsGlobalContext().lookupResult(Company.class);
companyLookup .addLookupListener(new LookupListener() {
#Override
public void resultChanged(LookupEvent le) {
Lookup.Result k = (Lookup.Result) le.getSource();
Collection<Company> cs = k.allInstances();
for (Company k1 : cs) {
selectedCompany = k1;
}
setCompanyTextFields(selectedCompany);
jTP_DataManagement.setVisible(true);
jPanel_Entiteti.setVisible(true);
}
});
}
A SearchResult which provides a lookup? Never seen this in the wild.
Please ask at nbdev#netbeans.org to get better feedback (probably from one of the NB devs)
I finally managed somehow to get what I want :
First off, define interface:
public interface ICodes {
public Code getCode();
}
Then, we implement quick search :
#ServiceProvider(service = ICodes.class)
public class ClientServicesQS implements SearchProvider, ICodes {
private static Code code = null;
#Override
public void evaluate(SearchRequest request, SearchResponse response) {
try {
for (Code c : INFSYS.queries.INFSistemQuery.ByersByName(request.getText())) {
if (!response.addResult(new SearchResult(c),
c.getName() + " ,Code: " + c.getByerCode()
+ (c.getAddress() != null ? ", " + c.getAddress() : ""))) {
return;
}
}
} catch (NullPointerException npe) {
StatusDisplayer.getDefault().setStatusText("Error." + npe.getMessage());
}
}
#Override
public Code getCode() {
return ClientServicesQS.sifra;
}
private static class SearchResult implements Runnable {
private final Code code;
public SearchResult(Code code) {
this.code= code;
}
#Override
public void run() {
try {
ClientServicesQS.code= this.code;
OpenTopComponent("ClientServicesTopComponent");
} catch (NullPointerException e) {
Display.messageBaloon("Error.", e.toString() + ", " + e.getMessage(), Display.TYPE_MESSAGE.ERROR);
}
}
}
}
Finally, we implement lookup in other module through platform.
Because I want to call lookup whenever componentOpen, oe componentActivated is invoked, it is usefull first to define :
private void QSCodeSearch() {
try {
ICode ic= Lookup.getDefault().lookup(ICode.class);
if ((code = ic.getCode()) != null) {
.
.
.
// setup UI components with data from lookup
.
.
.
}
} catch (Exception e) {
}
}
And when topcomponent is activated, we call QSCodeSearch() in :
#Override
public void componentOpened() {
...
QSCodeSearch()
...
}
...
#Override
public void requestActive() {
...
QSCodeSearch()
...
}