In my opinion all application exceptions (Business logic) exceptions should be checked exceptions.
Because, the client should be aware about the fact that the methods can throw an exception and be able to handle that exception.
This is as per the EJB spec, so no argument here.
In EJB if you throw a runtime exception the transaction will be rolled back, but maybe the business logic requires other handling...
For example:
In a method withdraw(500) if an InsufficientFundsException is thrown, you could withdraw as much as you can and go further. BUT if InsufficientFundsException is unchecked the transaction is already set for rollback....
It would be poor design to make InsufficientFundsException a RuntimeException when the client can recover from this.
The most obvious reason to invoke setRollbackOnly() is when you do not wish the transaction to commit when an application exception is thrown. Most likely, it because an update has already been done in the transaction. So, if your code throws application exception DuplicateKeyException and you want to rollback, you handle the exception by invoking setRollbackOnly() and then rethrowing DuplicateKeyException. Your searchLang method is an example.
I would like to clarify this comment of mine.
Check that your code is not throwing a checked exception, eg SQLException. If so, wrap it in EJBException and throw this exception.
This is better rewritten as follows.
Check that your code is not throwing a checked exception which is not an application exception, eg SQLException. If so, wrap it in EJBException and throw this exception.
If you allow SQLException to propagate to the container, it will be thrown to the client - who will not know what to do with it. This is why checked exceptions (SQLException being a common example) which are unexpected should be encapsulated in EJBException and thrown.
Remember, an application exception is always a checked exception but a checked exception is not always an application exception.