44

I'm working on a new codebase and migrating the system to a new framework.

There are a number of packages that I would like to deprecate, just to make it very clear to other developers that everything inside this package should not be used anymore for new development.

What is the best way to indicate that an entire package has been deprecated?

Daniel Alexiuc
  • 13,078
  • 9
  • 58
  • 73
  • 1
    notice there is a difference between deprecating everything inside the package vs deprecating the package itself. Deprecating the package itself is an indication that everything currently inside the package is deprecated **and** nothing should be added to this package – beluchin Sep 02 '16 at 11:52

6 Answers6

68

I had to do this recently and used the package-info.java file to deprecate the package.

http://www.intertech.com/Blog/whats-package-info-java-for/

Add a package-info.java file to your package with only the package declaration:

/**
 * @deprecated As of release 2.0, replaced by {@link com.acme.new.package}
 */
@Deprecated
package com.acme.old.package;

In Eclipse, all places where the user imports a class from this package will be underlined with a deprecation warning.

muymoo
  • 1,167
  • 2
  • 11
  • 16
  • 3
    As of Java 7, I believe this is the correct answer, as it is now possible to use @Deprecated as package annotations: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6492694 – Rafael Chaves Jun 09 '14 at 17:26
  • 4
    I believe `@deprecated` modifier is not allowed in the `package-info` level in the `javaDoc`. – Milli Oct 20 '15 at 18:16
  • @Milli see the first comment about the bug (fixed) in Java 7. – muymoo Oct 21 '15 at 18:35
  • 5
    @muymoo, I am using java 8 and it doesn't let me use the `@deprecated` modifier in my `JavaDoc`. Hence my earlier comment. – Milli Oct 22 '15 at 05:05
  • Hmm. In AndroidStudio it seams to have no effect so far :( – Giszmo Nov 05 '16 at 17:27
  • 4
    As of IntelliJ 2017.2 this does not mark classes inside the package, nor the package itself as deprecated. – christopheml Jul 19 '17 at 16:01
  • Note that the @Deprecated tag will be rejected [by eclipse] unless it's above the javadoc (2019.3). I don't know why. Also, use Java 9 to get the warning propagated properly: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6481080 – Stephen Aug 14 '19 at 21:35
  • @Stephen in Java 16 `@Deprecated` will be allowed in combination with the javadoc tag `@deprecated` (see [JDK-8160601](https://bugs.openjdk.java.net/browse/JDK-8160601)). Though this does not necessarily improve the situation because it is still unclear what the JDK developers actually want as behavior, multiple of the JDK bug reports contradict each other regarding this. – Marcono1234 Mar 05 '21 at 21:33
  • IntelliJ / JetBrains still doesn't show symbols declared inside the package in strikethrough in various views... You can upvote the feature here I think: https://youtrack.jetbrains.com/issue/IDEA-190089 – Kimball Robinson Jul 29 '22 at 19:14
15

You said it yourself: You want to deprecate everything that's inside a package, not the package itself. The package is nothing but a namespace and deprecating a namespace would have a different meaning - like don't use this namespace anymore. Like don't add any new items to that namespace.

In your case, I suggest you deprecate each public method (and field) of each class that shouldn't be used anymore. This becomes visible in modern IDE's and developers are warned when they want to use the old classes and methods. And you can look through your code and refactor it step by step to eliminate dependencies of those classes and methods.

Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • 10
    Hmm in my case that's a lot of annotations to add. I was hoping there was some way you could just do it at a package level once and the IDE would act in the same way as if you had done it on every method and field. – Daniel Alexiuc Feb 23 '11 at 04:34
  • 3
    You can mark as @Deprecated only every class in your package. No need to add annotation to ALL methods and fields. – Pavel Vyazankin Jul 23 '14 at 12:59
  • I added my solution in standard answer. – Pavel Vyazankin Jul 23 '14 at 13:51
  • 2
    _"The package is nothing but a namespace"_ Wrong. Packages and namespaces are different things entirely and work in different ways (e.g. namespaces can be nested within other namespaces). – code_dredd Oct 06 '18 at 22:39
  • 2
    This should no longer be the accepted answer. Java has had it's bugs fixed and `@Deprecated` on a package now works perfectly (Java 9). This answer is wrong enough that I'll downvote it at some point if it remains accepted (which isn't really fair to @Andreas_D) – Stephen Aug 14 '19 at 21:39
8

Use AspectJ. Create an Aspect that issues a compiler warning when the package is used:

public aspect DeprecationAspect{

    declare warning :
        call(* foo.bar..*(..)) : "Package foo.bar is deprecated";

}

(You can easily add AspectJ to your build if you use ant or maven)

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • @Joachim Many things are overkill: IDEs, version control, continuous integration, build systems etc. And still: I won't develop without them. AspectJ has this specific feature (among many others) that can't be easily achieved without AspectJ. Why not use it? It certainly does no harm, and it helps enforce policies. And to the person who downvoted this: Why? It's a valid suggestion. Can you show me _any_ other technology that can do the same in that few lines of code? – Sean Patrick Floyd Feb 22 '11 at 09:05
  • @Sean: I would presume that the person who downvoted thought it was a *bad* suggestion. – Lawrence Dol Jun 16 '11 at 20:26
  • @Software Monkey: well that's obvious. But I'd be interested in *why* they think it's a bad suggestion to use a standard technology that is designed exactly for tasks like this. – Sean Patrick Floyd Jun 17 '11 at 05:13
  • Again, I'm presuming, but to introduce something as heavy-weight as AspectJ solely to deprecate a package seems like extraordinary overkill. – Lawrence Dol Jun 17 '11 at 06:37
  • @Software Monkey, that is a valid opinion. I disagree, which is also valid, I guess. I am not complaining about your opinion, but about downvoting my suggestion of using a technology that exactly fits the problem. A comment: "That's too heavy" or any such thing would be fine, but a comment-less downvote is just plain ignorant. I guess some Java developers have a problem understanding that AspectJ [is becoming a huge part of Java development](http://www.indeed.com/jobtrends?q=aspectj). And about being heavy-weight: using it for compile-time checking does not add any runtime dependencies. – Sean Patrick Floyd Jun 17 '11 at 08:17
  • @Sean: To be clear, I did not downvote you - I was merely offering a response to your "downvoter... why?". And, by the way, a comment-less down-vote is perfectly acceptable and you need to stop whining. – Lawrence Dol Jun 17 '11 at 20:44
  • 2
    @Software Monkey I disagree. this is a site where highly qualified experts provide advice for free. Saying no thanks to free advice is acceptable, but downvoting others who took the time to provide an answer is only acceptable if the answer is terrible. And even then one should give the poster a chance to improve his answer by stating what you disagree with. You call that whining? I disagree. I call what you are doing bitching, and I guess you disagree. Let's leave it at that. To me, comment-less downvoters to working answers like this destroy this site. – Sean Patrick Floyd Jun 18 '11 at 07:20
  • 8
    And about overkill? My suggestion boils down to [adding < 20 lines to a maven pom](http://mojo.codehaus.org/aspectj-maven-plugin/usage.html) and writing a 3-line text file. Compare that with the accepted answer, deprecating every public field and method in a package manually. Now *that's* overkill! – Sean Patrick Floyd Jun 18 '11 at 07:44
2

For those who came later...
My solution with IDEA "Replace in Path"

Text to find: (public|protected)+(\s)(abstract)(\s)(static)(\s)(final)(\s)*(class|interface|enum|Enum)
Replace with: @Deprecated\n\$1 \$3 \$5 \$7 \$9
Options: (select) Regular expressions
Directory: {Choose dir}

Pavel Vyazankin
  • 1,470
  • 6
  • 18
  • 27
1

You can create Package annotation and deprecate any package with @Deprecated :)

Sergey Vedernikov
  • 7,609
  • 2
  • 25
  • 27
1

As mentioned by @muymoo before, you could use a package-info.java file. But all you can do is add a @deprecated warning in the JavaDoc of your file:

/**
 * @deprecated This package is deprecated, use {@link my.new.pkg} instead.
 */
package my.old.pkg;

JavaDoc is really your only option here, you cannot @Deprecate the package using a "proper" in-code annotation

@Deprecated
package my.old.pkg;

will lead to a compilation error in Java 8

$ java -version
java version "1.8.0_191"

$ javac package-info.java
package-info.java:6: error: modifier deprecated not allowed here

The only real, clean option here is to really deprecate all the classes in your package. Which does make sense, if you think about it, because a package in Java is nothing more then a namespace.

Stefan Haberl
  • 9,812
  • 7
  • 72
  • 81
  • 1
    If you remove the `@deprecated` JavaDoc tag and leave the `@Deprecated` annotation solely, it compiles correctly. – Bartosz Popiela May 05 '19 at 12:39
  • Read my answer: that's what I've written :D But honestly: What does it help adding a `@deprecated` JavaDoc to package-info? And what's the semantics of this? You simply **cannot** deprecate a package in Java. – Stefan Haberl May 06 '19 at 06:43