Question: I've been writing in Java and C# for a while, but I'm having a hard time identifying places where using a custom annotation would be advantageous.

I can see that JUnit uses annotations in test classes to identify the order it should run the methods in the test classes, which obviates the need for a configuration of some sort. 

What are other examples of problems that annotations solve elegantly?

Answer: 
As others pointed out, annotations are metadata about classes / properties / methods. In general, I find them most useful when data needs to be transformed between the Java domain and another domain or format, such as

* a database (this is what e.g. Hibernate / JPA is dealing with, using annotations heavily)
* an Excel sheet
* a legacy mainframe system

The latter two are real examples from the project I am working on.

Another, related task is data validation. We use the annotations of [Hibernate Validator](http://www.hibernate.org/subprojects/validator.html) (which is an implementation of JSR 303 - Bean Validation) to validate critical pieces of the data received from the above mentioned mainframe, before letting it enter our domain.

As others noted, all the information represented by annotations could in theory be represented in other forms, e.g. in distinct config files (in XML or other format). However, often it is just so much more convenient to have the annotations right there in the code, next to the entity it refers to. Typically (like in the above examples) the metadata represented by annotations is tightly tied to the code. So - once created - it very rarely changes independently of the corresponding code itself. So keeping it physically together with the code makes it cleaner and more maintainable.
I've been experimenting with using annotations to give executable specifications to code and generating unit tests for my [algebra project](https://github.com/mdgeorge4153/jalgebra). For example, I have an interface with a method to add two objects together, and the properties you would expect from additions are marked as annotations:

```
interface Group<E> extends Set<E> {
  @Commutative @Associative @Identity("zero") @Inverse("neg")
  E plus (E, E);

  E zero ();

  E neg (E e);
}

```

I have a (partially implemented) annotation processor that generates tests for these properties for any class that claims to implement this interface.  

This is an example of "user" annotations: `@Commutative`, `@Associative`, etc. are implemented as part of the algebra library, not as part of the annotation processing tool; generating new properties with tests is a simple matter of adding a new annotation type with a special method that checks the property.

Annotations have been moderately well-suited to this task, although there are a number of shortcomings. For example, java annotations do not have a notion of inheritance, so my processor has to explicitly search for annotations on all superinterfaces of a class. Also, Java doesn't support marking a method with multiple copies of the same annotation, so I can't write `@DistributesOver("foo")` and `@DistributesOver("bar")` on the same method.