TcpSocketClient- UnhandledException when I try read a response inside of a Task that not arrived yet - websocket

I'm using this library(https://github.com/rdavisau/sockets-for-pcl) to communicate with a TCP Server, that sends me when a event was generated, then, I have to verify all the time if the TCP Server sent to me a event, but if I try read anything before the TCP Server sends me, it's thrown the UnhandledException, but it only happens if I read inside a Task, in the main thread it thrown a timeout exception, the exception that I expected to happen in Task.
Someone can help me? Thanks. below is my code.
public class CentralTcpService
{
#region ConnectTcpAsync
public async void ConnectTcpAsync()
{
try
{
_sockecClient = new TcpSocketClient();
await _sockecClient.ConnectAsync(Central.Ip, Central.Port);
_writter = new ExtendedBinaryWriter(_sockecClient.WriteStream);
_reader = new ExtendedBinaryReader(_sockecClient.ReadStream);
_writter.WriteString(EvenNotProtocol.MobileReceiverCommand);
_sockecClient.ReadStream.ReadTimeout = int.MaxValue;
EnableTcpService();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
#endregion
#region TcpService
private void EnableTcpService()
{
_cancelationTcpService = new CancellationTokenSource();
new Task(StartService, _cancelationTcpService.Token, TaskCreationOptions.LongRunning).Start();
}
private void StartService()
{
while (!_cancelationTcpService.Token.IsCancellationRequested)
{
var ev = EvenNotProtocol.DeserializeEvent(_reader);
if (ev == null) continue;
_writter.WriteString(EvenNotProtocol.MobileOkCommand);
EventReceived?.Invoke(this, new CentralTcpEventArgs(ev));
}
}
}
public class EvenNotProtocol
{
public static Event DeserializeEvent(ExtendedBinaryReader reader)
{
try
{
reader.SkipBytes(1);
.....
}
catch (IOException e)
{
return null;
}
}
}

Related

Can I change Netty pipeline by events?

My app should do the next:
Send a POST request to server to get the token.
Connect to the websocket using this token in the headers while handshake.
Short question: To activate WebSocketClientProtocolHandler I have to fire event ctx.fireChannelActive() but from channelRead method because in this method I receive token from server . Is it correct place?
I implemented custom ChannelInboundHandlerAdapter and override:
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
authenticator.authenticate(ctx.channel()).addListener(new ChannelFutureListener() {
#Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if (!channelFuture.isSuccess()) {
authPromise.tryFailure(channelFuture.cause());
ctx.fireExceptionCaught(new RuntimeException("Auth is failed."));
} else {
ctx.fireUserEventTriggered("Auth is successful");
}
}
});
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (!(msg instanceof FullHttpResponse)) {
ctx.fireChannelRead(msg);
}
FullHttpResponse response = (FullHttpResponse) msg;
try {
authenticator.finishAuthentication(ctx.channel(), response);
authPromise.trySuccess();
ctx.pipeline().remove(this);
ctx.fireChannelActive();
} finally {
response.release();
}
}
Authenticator class adds needed handlers, sends POST request and then it should parse response from server and change the pipeline.
public class Authenticator {
private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
private final ObjectMapper mapper = new ObjectMapper();
private final MessengerConfig messengerConfig;
public Authenticator(MessengerConfig messengerConfig) {
this.messengerConfig = messengerConfig;
}
public ChannelFuture authenticate(Channel channel) {
this.preCheck(channel);
return this.authenticate(channel, channel.newPromise());
}
private void preCheck(Channel channel) {
ChannelPipeline pipeline = channel.pipeline();
HttpClientCodec httpClientCodec = pipeline.get(HttpClientCodec.class);
if (httpClientCodec == null) {
LOGGER.warn("Pipeline does not contain HttpClientCodec.");
pipeline.addFirst(HttpClientCodec.class.getName(), new HttpClientCodec());
LOGGER.info("HttpClientCodec was added to pipeline.");
}
HttpObjectAggregator httpObjectAggregator = pipeline.get(HttpObjectAggregator.class);
if (httpObjectAggregator == null) {
LOGGER.warn("Pipeline does not contain HttpObjectAggregator.");
pipeline.addAfter(
HttpClientCodec.class.getName(),
HttpObjectAggregator.class.getName(),
new HttpObjectAggregator(8192)
);
LOGGER.info("HttpObjectAggregator was added to pipeline.");
}
}
private ChannelFuture authenticate(Channel channel, ChannelPromise promise) {
HttpRequest request = createAuthRequest();
try {
channel.writeAndFlush(request).addListener(new ChannelFutureListener() {
#Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if (channelFuture.isSuccess()) {
promise.setSuccess();
} else {
promise.setFailure(new RuntimeException(""));
}
}
});
} catch (Exception e) {
LOGGER.error("Error", e);
}
return promise;
}
public void finishAuthentication(Channel channel, FullHttpResponse response) {
ByteBuf content = response.content();
AuthenticationData authenticationData = null;
try {
authenticationData = this.mapper.readValue(content.toString(CharsetUtil.UTF_8), AuthenticationData.class);
} catch (JsonProcessingException e) {
LOGGER.error("Can't parse authentication data.", e);
throw new RuntimeException((e));
}
LOGGER.info(Objects.toString(authenticationData));
DefaultWebSocketClientProtocolHandlerFactory factory = new DefaultWebSocketClientProtocolHandlerFactory();
WebSocketClientProtocolHandler handler = factory.getHandler(this.messengerConfig, authenticationData);
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast(WebSocketClientProtocolHandler.class.getName(), handler);
LOGGER.info("WebSocketClientProtocolHandler was added.");
pipeline.addLast(MessageHandler.class.getName(), new MessageHandler());
LOGGER.info("MessageHandler was added.");
}
So here I have two stages:
Auth stage with a pipeline:
io.netty.handler.codec.http.HttpClientCodec
io.netty.handler.codec.http.HttpObjectAggregator
AuthenticationHandler
2 Web-socket stage with a pipeline:
io.netty.handler.codec.http.HttpClientCodec
io.netty.handler.codec.http.HttpObjectAggregator
io.netty.handler.codec.http.websocketx.WebSocketClientProtocolHandshakeHandler
io.netty.handler.codec.http.websocketx.Utf8FrameValidator
io.netty.handler.codec.http.websocketx.WebSocketClientProtocolHandler
com.github.apsyvenko.client.messaging.MessageHandler
To activate second stage I have to fire event - ctx.fireChannelActive() but from channelRead.
As a result I got an exception:
18:19:37.055 [nioEventLoopGroup-2-1] WARN i.n.channel.DefaultChannelPipeline - An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
java.net.SocketException: Connection reset
after hand-shake had started.

Issue in managing Hibernate transactions

I am using a thread based approach to poll the status of a specific task on AWS. For this, I use a while loop to constantly check the status as shown in below code. The issue is that when the code switches from one Service to another, it runs into an error -
Could not obtain transaction-synchronised hibernate session
The function in the thread is as below:
Runnable task = new Runnable() {
#Override
public void run() {
Session session = null;
try {
session = sessionFactory.openSession();
RmlWorkspace rmlWorkspace = session.get(RmlWorkspace.class, id);
logger.info("Starting Status check for "+id);
if (rmlWorkspace.getCloudStack().getStatus() == RUNNING_STATUS.STARTING) {
while (rmlWorkspace.getCloudStack().getStatus() != RUNNING_STATUS.ON) {
logger.info("Checking Status for "+id);
rmlWorkspace = checkStatus(session, rmlWorkspace);
TimeUnit.SECONDS.sleep(5);
}
} else if (rmlWorkspace.getCloudStack().getStatus() == RUNNING_STATUS.STOPPING) {
while (rmlWorkspace.getCloudStack().getStatus() != RUNNING_STATUS.OFF) {
Transaction tx = session.beginTransaction();
rmlWorkspace = checkStatus(session, rmlWorkspace);
tx.commit();
TimeUnit.SECONDS.sleep(5);
}
}
session.close();
} catch (Exception e) {
logger.info(e.getMessage());
if (session != null)
session.close();
}
}
};
The checkStatus function tries to call a function inside another class with the annotation #Service. The code meets an error at the below code:
private AssumeRoleResult assumeRole() {
try {
BasicAWSCredentials credentials = new BasicAWSCredentials(configAttributeService.getAttribute("aws.iamkey"),
configAttributeService.getAttribute("aws.iampass"));
AWSSecurityTokenService client = AWSSecurityTokenServiceClientBuilder.standard()
.withRegion(Regions.US_WEST_2).withCredentials(new AWSStaticCredentialsProvider(credentials))
.build();
AssumeRoleRequest request = new AssumeRoleRequest()
.withRoleArn(configAttributeService.getAttribute("aws.assumerole"))
.withRoleSessionName(UUID.randomUUID().toString()).withDurationSeconds(900);
AssumeRoleResult assumeRoleResult = client.assumeRole(request);
return assumeRoleResult;
} catch (Exception e) {
throw e;
}
}
The class containing the above function has an annotation #Service("xxx")
Could someone explain the reason for this and how to get this working.

kryonet client, send message to server without open a new connection

I'm saying i'm not a programmer but a guy who has been learning to program with java for a while. I hope to find the solution to my problem here. I'm trying to program my home automation system and remote control and to do this, I chose to use Kryonet. My problem is that every time I send the data to the server, the client opens a new connection. It's been 3 weeks since googlo and I try to figure out how to do it but with no results.
Every help is seriously appreciated. This is my code. Thank you.
This code work in my home network.
Sorry for my english...
public class MainActivity extends AppCompatActivity {
Button button;
String IP = "";
EditText editText;
TextView textView;
EditText editText3;
public static String msg_response;
public static String msg_request;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Handler handler = new MyHandler();
button = (Button) findViewById(R.id.button);
editText = (EditText) findViewById(R.id.editText);
editText3 = (EditText) findViewById(R.id.editText3);
textView = (TextView) findViewById(R.id.textView);
int MY_PERMISSIONS_REQUEST_INTERNET = 1;
int MY_PERMISSIONS_REQUEST_ACCESS_NETWORK_STATE = 1;
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.INTERNET},
MY_PERMISSIONS_REQUEST_INTERNET);
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_NETWORK_STATE},
MY_PERMISSIONS_REQUEST_ACCESS_NETWORK_STATE);
int MY_PERMISSIONS_REQUEST_ACCESS_WIFY_STATE = 1;
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_WIFI_STATE},
MY_PERMISSIONS_REQUEST_ACCESS_WIFY_STATE);
textView.setText(msg_response);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
msg_request = valueOf(editText3.getText().toString());
} catch (Exception e) {
e.printStackTrace();
}
MyThread myThread = new MyThread(handler);
myThread.start();
}
});
}
private class MyHandler extends Handler {
#Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
if (bundle.containsKey("msg da server")) {
String msgin = bundle.getString("msg da server");
textView.setText(msgin);
}
}
}
class MyThread extends Thread {
private Handler handler;
public MyThread(Handler handler) {
this.handler = handler;
}
public void run() {
System.out.println("MyThread running");
Client client = new Client();
client.start();
Kryo kryoClient = client.getKryo();
kryoClient.register(SampleRequest.class);
kryoClient.register(SampleResponse.class);
try {
client.connect(5000, "192.168.0.101", 54555, 54666);
} catch (IOException e) {
e.printStackTrace();
}
client.addListener(new Listener() {
public void received(Connection connection, Object object) {
if (object instanceof SampleResponse) {
SampleResponse response = (SampleResponse) object;
System.out.println(response.text);
msg_response = response.text.toString();
invia_activity(msg_response);
}
}
});
SampleRequest request = new SampleRequest();
request.text = msg_request;
client.sendTCP(request);
}
private void invia_activity(String invia) {
Message msg = handler.obtainMessage();
Bundle b = new Bundle();
b.putString("msg da server", "" + invia);
msg.setData(b);
handler.sendMessage(msg);
}
}
}
I dont have an direct solution, but i have an tutorial for it. I used the same one. So there the connections keeps open, and you can send as many packets as you need. Its without audio, but the code works well. After that you can experiment with the code. It works fine for me. This is the tutorial
I hope i can help you with this.
EDIT:
Maybe you can make an
public static Connection conn;
and you could use that object again and again as your connection to the server.

android async task executing api's repeteadly

I am using Android Async Task function to execute an api using urlconnection. this api in turn sends emails to selected users.Now the issue is I am getting spammed by these emails at first I thought of it as an server side issue or my script but I created a new api and used it on IOS version of my application and everything works fine.But when I execute it on android I start getting spams,so I think the Issue lies in my android programming.
public class submitparse extends AsyncTask<String ,String,String> {
String Url;
#Override
protected String doInBackground(String... params) {
URL phonelink;
HttpURLConnection urlConnection = null;
try {
phonelink = new URL(params[0]);
urlConnection = (HttpURLConnection) phonelink
.openConnection();
urlConnection.connect();
InputStream in = urlConnection.getInputStream();
InputStreamReader isw = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isw);
String line = "";
StringBuffer buffer = new StringBuffer();
while ((line = br.readLine()) != null) {
buffer.append(line);
}
String finalresult = buffer.toString();
return finalresult;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
urlConnection.disconnect();
} catch (Exception e) {
e.printStackTrace(); //If you want further info on failure...
}
}
return null;
}
I am using this command to call it..
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String link = "";
new submitparse().execute(link);
}
});
On getting result I start another activity,where link is a string containing url.
If you don't care, you can also use just a new Thread. That should fit your needs and works fine. As far as I read, you don't need to use an AsyncTask and therefore IMO a normal Thread would be better.
// Runnable uiThreadRunnable = new Runnable.....
Handler handler = new Handler(); // import android.os.Handler
Runnable runnable = new Runnable() {
public void run() {
// do your stuff
// use 'handler.post(uiThreadRunnable);' to if you NEED to run something on main thread
}
};
Thread thread = new Thread(runnable);
thread.start();

Adobe CQ : Regarding Session in Event Listener

I have a question regarding event listener. We have a event listener which listen to delete node event and perform some activity say "send email".
While code review i found this, although this code is working fine i am not convinced with the session being handled here :
#Activate
protected void activate(ComponentContext context) {
try{
final String path="/content/dam/";
Session session = repository.loginAdministrative(repository.getDefaultWorkspace());
observationManager = session.getWorkspace().getObservationManager();
observationManager.addEventListener(this, Event.PROPERTY_REMOVED, path, true, null, null, true);
checkOutProperty = OsgiUtil.toString(context.getProperties()
.get(ASSET_LOCK_PROPNAME_UPDATE), ASSET_LOCK_PROPNAME_DEFAULT);
if (session != null && session.isLive()) {
session.save();
}
} catch (RepositoryException e) {
if(LOG.isErrorEnabled()){
LOG.error("Error Occured in activate method of Property Removed Listener class:" + e.getMessage());
}
}catch (Exception e) {
if(LOG.isErrorEnabled()){
LOG.error("Error Occured in activate method of Property Removed Listener class:"+e.getMessage());
}
}
}
#Deactivate
protected void deactivate(ComponentContext componentContext) {
try {
if (observationManager != null) {
observationManager.removeEventListener(this);
}
} catch (RepositoryException e) {
if(LOG.isErrorEnabled()){
LOG.error("Error Occured " + e);
}
} catch (Exception e) {
if(LOG.isErrorEnabled()){
LOG.error(e.getMessage());
}
}
}
Questions:
Best practice would be to create session object private to this class and should be logout in deactivate method?
Once an event is added in Observation Manager, do we really need session object? I was expecting if we should logout from session there.
EventListener are a bit cumbersome here. I fought many battles with JCR Sessions and Sling ResourceResolvers within them. The problem is, you need to keep the Session active as long as the Event Listener is active. So the only thing missing in your code is a logout on deactivate.
I created an AbstractEventListener which takes care of this and provides the following two methods and has two private members:
private Session session;
private ObservationManager observationManager;
protected void addEventListener(final EventListener eventListener,
final int eventTypes, final String path, final String[] nodeTypes) {
try {
session = getRepositorySession();
observationManager = session.getWorkspace().getObservationManager();
observationManager.addEventListener(eventListener, eventTypes,
path, true, null, nodeTypes, true);
} catch (RepositoryException e) {
LOGGER.error("Repository error while registering observation: ", e);
}
}
protected void removeEventListener(final EventListener eventListener) {
if (observationManager != null) {
try {
observationManager.removeEventListener(eventListener);
} catch (RepositoryException e) {
LOGGER.error(
"Repository error while unregistering observation: ", e);
} finally {
logoutSession(session);
}
}
}
And then in the actual EventListener I just call them:
protected void activate(ComponentContext context) {
addEventListener(this, Event.PROPERTY_ADDED| Event.PROPERTY_CHANGED, "/content/mysite", null);
}
}
protected void deactivate(ComponentContext componentContext) {
removeEventListener(this);
}

Resources