sjyn
sjyn

Reputation: 99

How To Make Java Annotations Useful

In a project that I'm working on, I would like to have a custom annotation that warns users that this specific method should be called from another thread. I've called it @ThreadNeeded, and I want to achieve the effect of having the compiler warn the user if the method called would be on the main thread. How can I achieve this? I have looked into many guides on Annotations, but none of them actually give a way to make use of them other than just marking the ElementType with the annotation. Here is the source of the annotation I have so far

/**
 * An annotation that signifies that this method needs to be run inside a background thread.
 */
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface ThreadNeeded {

}

And here is an example usage

    @Nullable
    @ThreadNeeded
    public SonyCamera build(){
        try {
            send();
        } catch (Exception ex){
            Log.e(TAG, ex.getMessage(), ex);
            return null;
        }
        return camera;
    }

    private void send() throws Exception {
        final byte[] ssdpreqb = SSDP_REQUEST.getBytes();
        DatagramSocket socket;
        DatagramPacket recieve, packet;
        socket = new DatagramSocket();
        InetSocketAddress isad = new InetSocketAddress(SSDP_ADDRESS, SSDP_PORT);
        packet = new DatagramPacket(ssdpreqb, ssdpreqb.length, isad);
        socket.send(packet);
        Thread.sleep(100);
        socket.send(packet);
        Thread.sleep(100);
        socket.send(packet);

        boolean searching = true;
        byte[] array = new byte[1024];
        while(searching) {
            recieve = new DatagramPacket(array, array.length);
            socket.setSoTimeout(SSDP_TIMEOUT);
            socket.receive(recieve);
            String replyMessage = new String(recieve.getData(), 0, recieve.getLength(), "UTF-8");
            String ddusn = SSDPClient.findParamaterValue(replyMessage, "USN");
            String location = SSDPClient.findParamaterValue(replyMessage, "LOCATION");
            camera.location = location;
            camera.usn = ddusn;
            fetch(location);
        }
    }

Upvotes: 0

Views: 211

Answers (2)

user882813
user882813

Reputation: 835

In order to process annotations while compiling sources you should write annotation processor and instruct javacto use them.

Here is some kind of tutorial: https://www.javacodegeeks.com/2015/09/java-annotation-processors.html

Though I'm not sure you can detect mentioned threading issues at compile-time.

Upvotes: 1

mernst
mernst

Reputation: 8147

The GUI Effect Checker may do what you need. The below is taken from its documentation:

One of the most prevalent GUI-related bugs is invalid UI update or invalid thread access: accessing the UI directly from a background thread.

The GUI Effect Checker solves this problem. The GUI Effect Checker ensures that only the UI thread accesses UI objects. This prevents GUI errors such as invalid UI update and invalid thread access.

The programmer annotates each method to indicate whether:

  • It accesses no UI elements (and may run on any thread); such a method is said to have the “safe effect”.
  • It may access UI elements (and must run on the UI thread); such a method is said to have the “UI effect”.

At compile time, the GUI Effect Checker issues errors in the following cases:

  • A @UIEffect method is invoked by a @SafeEffect method.
  • Method declarations violate subtyping restrictions: a supertype declares a @SafeEffect method, and a subtype annotates an overriding version as @UIEffect.

Upvotes: 1

Related Questions