My (Android) app needs a network scanner feature.
I want to give it a subnet and I want it to send a request to each possible address on the subnet and determine whether or not it's responsive.
I have two classes:
Device, which contains an address and a property available (bool) (that can be set by the method checkAvailable).
NetworkerScanner, which extends Thread and instantiates all the Devices.
Eventually, I plan to have an object that is an observer on an Observable collection that will contain all the available devices.
Adding the available Devices to the Collection is not obvious.
Algorithm
Let col be a Observable Collection
For each possible address
Instantiate a corresponding Device
On a new, separate thread, get this new device's availability.
If it's available, then add it to col.
Checking device's availability is not immediate (I'm using Volley, which uses callbacks).
How can I, from my HTTP request callback, add the Device to the collection?
I have several ideas:
Pass a reference to the collection to the device when instantiating it, which seems like a bad idea, since the collection doesn't have a reason to be a property of the Device. More than that, if I wanted to run multiple scans on the same Device instances, it wouldn't work anymore since a Device could only have one Collection.
I could also pass a reference to the collection to the checkAvailable method, but I feel like this is a trick (and a trick of the wrong type of tricks).
When calling checkAvailable, pass a reference to an onResponseListener (the callback method for the HTTP request) to it. Since I would have created the listener in my NetworkScanner, I could capture the local collection. But I feel this is wrong. Like... very wrong.
Please suggest.
Related
I created a never ending service but I'm not sure that it's OK to do what I did with this service. I declared global variable like static String list_contact
and fill the list from a db in onCreate method. I wanted to avoid to retrieve data from database each time because I need to compare to the list fast. But maybe it's a problem to store data in global variable of Service. Plus I need another list with thousands of data. If it's no good, can I find a compromise between memory and speed for retrieving data ? Thanks.
Its not a great idea put the static variable in Service and assume that service would run forever.
The biggest drawback is, service won't run in background forever, starting from Android O. Latest version applies more restrictions on the background processing and kills your service few minutes after app is put in background.
You can implement Object pool pattern which will store the frequently accessed data in an Object. This doesn't require to have a service running and could serve your purpose. You need to ensure that you are not maintaining sensitive data in clear text in these Objects.
Alternatively, you can also read this post which describes caching for Android.
I'm looking for something similar to RemovalListener/RemovalNotification - but notification of when values in the cache are modified. Notification would include the old value, as well as the new value that has just been added.
[update]
I only populate the cache via a CaceLoader (load & reload). The "source" of the cached elements are at times flakey (remote to the cache).
So the two primary reason for having the replacement element as well are:
Debug logging to indicate when/what values are actually retrieved
from the remote source. This one could be accomplished in a class
that does the remote retrieval.
Generate difference that can then be proactively pushed to (remote)
clients. e.g. publishing changes via blazeDS, rather than requiring
the clients to continuously "get".
It should be possible to implement this without additional notification via the reload method, and getting the current cache contents before going off and getting the new value, and then comparing the new value and the previous value - and then taking additional action. I was looking for a more generic way to decouple the modification notification.
Thanks.
You could file a Guava feature request asking for a method to be added to RemovalNotification that would return the replacement value when the cause is REPLACED. But please provide as much detail as possible about your problem and why this is a good solution for it.
What are the key points in checklist to be checked while implementing good serialization in java (I'm not really looking for , implements Serializable, write, readObject etc).
Instead , How to reduce the size of the object , Probably how to make the object in zip format and send over the network etc..
How to ensure the secure mode of transfer.
any others like this..
How to reduce the size of the object: new ObjectOutputStream(new GZipOutputStream(new BufferedOutputStream(out)). But this is a space-time tradeoff. You may find that it makes performance worse by adding latency.
How to ensure the secure mode of transfer: SSLSocket or an HTTPS URL.
Any others like this
Any others like what? You will need to be specific.
Do not use serialization to "persist" objects - this makes schema management (i.e. changing what constitutes a class's state) almost unworkable
Always declare a serialVersionUID field; otherwise you will not be able to add methods, or change the class in any way (even non-state-changing ones) without old versions of your code being unable to deserialize the objects (an IncompatibleClassVersionError will be thrown)
try and override readResolve if you are deserializing a logical "enum" instance of a class (typesafe enumeration pattern)
Make sure you are 100% happy with the name of the variables which make up the state of your class. Once you have serialized instances around, you cannot change the variable names
Do not implement Serializable unless you really have to
Do not make your interfaces Serializable - the implementation classes may be, but the interfaces should not be
Do not make serialization part of the way your library passes objects around, unless you are the only producer and consumer of the objects (e.g. server-GUI communication). Use a binary/wire protocol instead (e.g. protobuf)
To minimize what is sent over the wire, you could use swizzling. That is, perhaps you have a Product class; the serialized form might just be a unique int id field. All other methods could then be made to construct relevant state as required (perhaps as a database call, or call to some central service)
Make sure, if you are serializing out an object which contains some collection of elements as part of its state, that you synchronize on the collection. Otherwise you may find that someone modifies the collection as it is being serialized out, resulting in a ConcurrentModificationException
Probably how to make the object in zip format and send over the network etc..
Check out how the game developers for network games implement networking. They know, how to transmit data quickly. Have a look at e.g. http://code.google.com/p/kryonet/
How to ensure the secure mode of transfer. any others like this..
There are a lot of interpretations of secure mode. If you need reliability, use TCP otherwise UDP. If you need encryption use TLS otherwise rot13 may fit. If you need to ensure integrity, append a hash of the values to the message.
How to reduce the size of the object ,
Analyse your data and strip down the objects, so that you only have the necessary data in there. This is very context specific, as the best optimisation can be in the domain. E.g. you can check, if it is possible to send only deltas of the change.
It is an interesting question, but you have to be more specific about your goal or domain to get an answer that fits best.
I have a list of services which can be identified by names. Every service has a set of parameters (IP address, port, availability and so on). There are also method which can be applied to the services (close connection, open connection, send a message to the server, check if it is responding and so on).
So, I thought it is a natural approach to create a Server class and represent real servers as objects of this class.
But than I realized that it is not really convenient. For example I have a name of the server (just a string) and I would like to do something with this server. Then I need to have a map which maps name of the server to the object representing this server? It does not seems to be an elegant solution.
What I decided is to have a class containing a set of static methods. And then, for example to use it in the following way: ServerClass.sendMessage("NameOfServer","MyMessage") or for example ServerClass.close("NameOfServer") or ServerClass.getIP("NameOfServer").
Is it a good solution?
An advantage of having a class with various instances is that it provides a kind of type safety. If you have
Server myServer = ServerRepository.getServer("NameOfServer");
if (myServer != null) myServer.sendMessage("MyMessage");
then you know before you send the message if your server name has a typo in it (because your repository can't return a matching message).
Do all of your servers expose the same services, or are there some that are dependent on the server. As an example if you have both FooServers which have a method doFoo() and BarServers with a method doBar() but Foo has no doBar and Bar has no doFoo, then this is likely a bad idea as your ServerClass will potentially expose methods that are meaningless to potential callers. If however you know all of your servers are going to be FooServers than this may be a valid approach as you can centralize common code. I would say be careful that your code remains maintainable and you are not forcing common behavior where it needs to be customized, or you end up adding a multitude of extra arguments to indicate "special cases" where you need to the behavior to vary slightly for one reason or another.
In my implementation of Java NIO I have not been able to get SelectionKey.attach() to work. Basically, once clients connect (OP_ACCEPT interest ops) I add them to a map where their IP address maps to an object that maintains state for the client. Then, when an OP_READ occurs, I again retrieve the client's IP address, and this time get the value from the map and get the client's state object that way.
The problem here is that I have to do a map lookup EVERY TIME data is read from the network. There is a lot of wasted work going on there. So, I was thrilled to see that you can attach an arbitrary object type to a SelectionKey, which should be easily retrieved when you call SelectionKey.attachment(), even if we are now handling a different event (retrieved during OP_READ versus put into the map during OP_ACCEPT).
The problem is that it doesn't work. When I retrieve the attachment, it is always null. And if I set up the attachment via attach() and then immediately call attachment(), it does work. Somehow between different events, it loses its association.
I'm sorry, my code is a bit long to post here, but if you look at the comments in this thread:
link text
...You will see that some others have basically come to the same conclusion: that attach() and attachment() don't work, and never have.
Is there a trick to get it to work, or am I stuck with the evil overhead necessary of manually doing a lookup in a map EVERY TIME there is a new read event to handle?
Finally, is there a way to "wrap" SelectionKey in a new subclass that will properly handle attach() and attachment()?
Thanks!
I have successfully attached objects to SelectionKeys without any problems, but only from the same event. For example the first time I get an OP_READ, I attach an object to the SelectionKey and on subsequent reads I retrieve it, and it works fine. Maybe OP_ACCEPT and OP_READ handle different keys because they're different events, but I think the SelectionKey should be the same for the same connection... however if you make different connections even from the same IP you will get different SelectionKeys.
UPDATE: I just checked my code and there is something very important: I didn't call attach() at all; I used the SelectableChannel.register(Selector sel, int ops, Object att) method. If you do that, subsequent calls to attachment() on the SelectionKey will work.
There is no CR in your linked page, and I can't see anything on bugs.sun.com. However, attach/attachment is very simple code (although slightly more complicated after my bug. My guess is that you are getting a different SelectionKey, so trying to wrap it would be pointless.