I am writing a library in Java. I've divided its implementation into Java packages to help manage the complexity. Only one package contains classes that are visible to clients of the library. However, because only public methods are visible outside of the package for use by other packages of the library, I find myself forced to do one of the following:
(1) Only put interfaces and factory methods in the externally-visible package, putting implementations of those interfaces in a separate package, as described in this SO answer. For example external.MyInterface and internal.MyInterfaceImpl. I find this messy.
(2) Make both internal and external methods public in the external package, and attach Javadoc tags to the internal methods so I can remove their docs prior to publication, either manually (error-prone) or by writing some sort of Javadoc preprocessor or postprocessor.
(3) Use a mechanism that Javadoc provides for this purpose -- ideally, a Javadoc tag.
Whatever the approach, all I really care about is having a consistent way to automatically generate Javadocs for just the external APIs. Is there a standard way to do this? A tool for the purpose?
An alternative solution I've been using for years is to add an #exclude tag, using the public domain code provided in this blog: Implementing #exclude using Dynamic Proxies.
To exclude a Java element (attribute, method, constructor, class, inner class or package) from the Javadoc output, just add the #exclude tag in its Javadoc:
public class MyClass {
/**
* This is my internal attribute, javadoc not exposed.
* #exclude
*/
protected String myInternalAttribute;
/**
* This is my external attribute, javadoc is exposed.
*/
protected String myExternalAttribute;
/**
* This is my internal method, javadoc not exposed.
* #exclude
*/
public void myInternalMethod() { }
/**
* This is my external method, javadoc is exposed.
*/
public void myExternalMethod() { }
}
I found these two answers elsewhere on SO. One approach is to create a custom Javadoc annotation and have an Ant task replace the annotation with deprecated prior to generating the Javadoc. The other, far simpler approach is to use Doxygen's conditional inclusion.
I'm not stuck with Javadoc, so I could go with Doxygen. However, looking at Doxygen right now, it's so different from Javadoc that I'm not sure it's worth the learning curve or establishing a precedent just to be able to generate external APIs.
Here's another solution I will try next time I'm in a position to build: I'll demarcate the portions of the source files that are internal-only, write a tool that duplicates the source files of the external package while removing the portions of the files that are demarcated internal-only, and then run Javadoc off of the generated source. This should work unless Javadoc needs the linker to be happy.
I don't know if it's worth keeping my question around. Might help others find the answer, should they be thinking about it the way I was. Even so, no one has presented a great solution yet.
Related
I am trying to achieve something similar to the C# preprocessor. I am aware that Java does NOT have the same preprocessor capabilities, and am aware that there are ways to achieve similar results using design patterns such as Factory. However, I am still interested in finding a solution to this question.
Currently, what I do is create a class that contains several static final boolean attributes, such as the following example:
public class Preprocessor
{
public static final boolean FULLACCESS = false;
}
I then use this in the following manner:
public ClassName getClassName()
{
if(Preprocessor.FULLACCESS)
{
return this;
}
else
{
return this.DeepCopy();
}
}
So far so good, this solves my problem (the example above is trivial, but I do use this in other instances where it is helpful). My question is, would there be a way to place the conditional around an entire method, so that the method itself would be unavailable given the correct "Preprocessor" variables? For example, I would like to be able to make a specific constructor available only for packages that are given "Full Access", as follows:
public ClassName()
{
// do things
}
if(FULLACCESS)
{
public ClassName(ClassName thing)
{
// copy contents from thing to the object being created
}
}
Again, I am aware of the limitations (or design decisions) of Java as a language, and am aware that in most circumstances this is unnecessary. As a matter of fact, I have considered simply creating these "extra" methods and placing the entire code of them within a conditional, while throwing an Exception if the conditional is not active, but that is a very crude solution that does not seem helpful to my programmers when I make these libraries available to them.
Thank you very much in advance for any help.
Edit:
To complement the question, the reason why I am attempting to do this is that by using exceptions as a solution, the IDE would display methods as "available" when they are actually not. However, again, it might just be a case of my being ignorant of Java.
The reasons for my wanting to do this are primarily so that I may have more than one public interface available, say, one restrictive where control is tighter within the methods, and one more permissive where direct alteration of attributes is allowed. However, I do also want to be able to actively remove portions of code from the .class, for instance, in a Product Line development approach where certain variants are not available.
Edit2.:
Furthermore, it is important to note that I will be generating the documentation conditionally as well. Therefore, each compiled version of the packages would have its own documentation, containing only that which is actually available.
Well, you can make it happen. A word of caution, though...
I can only think of one time when I thought this kind of approach was the best way, and it turned out I was wrong. The case of changing a class's public interface especially looks like a red flag to me. Throwing an exception when the access level isn't high enough to invoke the method might be more code-friendly.
But anyway, when I thought I wanted a preprocessor, what I did was to write one. I created a custom annotation to place on conditionally-available methods, grabbed a Java parser and wrote a little program that used the parser to find and remove methods that have the annotation. Then add that (conditionally) to the build process.
Because it turned out to be useless to me, I discarded mine; and I've never seen anyone else do it and publish it; so as far as I know you'd have to roll your own.
This answer is based partially on the comments you have left on the question and on Mark's answer.
I would suggest that you do this using Java interfaces which expose just the API that you desire. When you need a less restrictive API contract, extend an interface or create a separate implementation of an existing interface to get what you need.
public interface A
{
void f();
}
A above is your general API. Now you want to have some special extra methods to test A or to debug it or manipulate it or whatever...
public interface B extends A
{
void specialAccess();
}
Also, Java now supports default method implementations for interfaces which might be useful to you depending on how you implement your API. They take the following form...
public interface A
{
List getList();
// this is still only an interface, but you have a default impl. here
default void add(Object o)
{
getList().add(o);
}
}
You can read more about default methods on Oracle's page about it here.
In your API, your general distribution of it could include A and omit B entirely, and omit any implementations that offer the special access; then you can include B and special implementations for the special access version of the API you mentioned. This would allow plain old Java objects, nothing different to the code other than an extra interface and maybe an extra implementation of it. The custom part would just be in your packaging of the library. If you want to hand someone a "non-special" low-access version, hand them a jar that does not include B and does not include any possible BImplementation, possibly by having a separate build script.
I use Netbeans for my Java work, and I like to let it use the default build scripts that it auto generates. So if I were doing this and I were doing it in Netbeans, I would probably create two projects, one for base API and one for special-access API, and I would make the special-access one dependent on the base project. That would leave me with two jars instead of one, but I would be fine with that; if two jars bothered me enough I would go through the extra step mentioned above of making a build script for the special access version.
Some examples straight from Java
Swing has examples of this kind of pattern. Notice that GUI components have a void paint(Graphics g). A Graphics gives you a certain set of functionality. Generally, that g is actually a Graphics2D, so you can treat it as such if you so desire.
void paint(Graphics g)
{
Graphics2d g2d = Graphics2d.class.cast(g);
}
Another example is with Swing component models. If you use a JList or a JComboBox to display a list of objects in a GUI, you probably do not use the default model it comes with if you want to change that list over time. Instead, you create a new model with added functionality and inject it.
JList list = new JList();
DefaultListModel model = new DefaultListModel();
list.setModel(model);
Now your JList model has extra functionality that is not normally apparent, including the ability to add and remove items easily.
Not only is extra functionality added this way, but the original author of ListModel did not even need to know that this functionality could exist.
the only way in Java to reach that is to use preprocessor, for instance PostgresJDBC team uses java comment preprocessor for such manipulations, here is example from their Driver.java
//#if mvn.project.property.postgresql.jdbc.spec >= "JDBC4.1"
#Override
public java.util.logging.Logger getParentLogger() {
return PARENT_LOGGER;
}
//#endif
With Gradle you can manage your sources and I think that no preprocessor macros are no longer needed. Right now in src directory you have main/java with all sources but if you need specific methods in e.g. debug and release builds to do / or not specific things then create debug/java and release/java in src and put YourClass there. Note that by doing this you'll have to have YourClass in debug/java and release/java but not in main/java.
According to the link, i wrote the following code:
/**
* #hide
* */
public void myMethod() {
// do something
}
When i use the command to generate the doc:
$ javadoc -locale en_US -encoding UTF-8 -charset UTF-8 -d doc xxx.java
The doc still have the myMethod item. So how to hide the myMethod? What did i miss ?
You are using a Doclava tag, but are generating the API documentation using the standard doclet.
Building Doclava
The Doclava source comes bundled with an ant script to build the doclet. The "jar" task will build a jar containing Doclava and all necessary dependencies.
Using Doclava with Javadoc
The command line arguments to pass to Javadoc to use Doclava are: -doclet com.google.doclava.Doclava -docletpath ${jar.file}
As per the official Javadoc FAQ, hiding public members is currently not possible in a direct way.
Occasionally you might need to make a class or method public so that it can be accessible from other packages, not because you want it to be part of the public API. Having these methods appear in the documentation merely confuses application developers.
There is currently no Javadoc option to hide, exclude or suppress public members from the javadoc-generated documentation.
Several options are available:
Excluding source files - You can pass into javadoc only the source filenames for all classes you want to document, and exclude those you want to omit. Notice this has the granularity of files, not classes. Therefore, if you exclude a source file that contains nested classes, they would also be excluded. (You can put the list of classes in a command line argument file rather than directly on the command line.) The default Javadoc offers no way to omit classes when passing in package names on the command line.
Excluding individual classes - You can use the Exclude Doclet. This has finer granularity (class rather than source file) than the previous option, and would be more natural to use because you explicitly list in a file the files you want to exclude.
Excluding classes, methods and fields - The yDoc Doclet has this capability, where you mark items with an exclusion tag in the source code. In addition, anyone is welcome to extend the Exclude Doclet above for methods and fields -- we'd be happy to publish it and add your name to the credits.
We are considering #exclude as a proposed tag for excluding members.
Also check out the Proposed Javadoc Tags page for more info into #exclude and #hide.
Use #hidden tag as below, it was introduced in JDK 9 and works with JDK 17 as well.
class Test {
/**
* This is hidden
* #hidden
*
* #param a
* #param b
*/
public int add(int a, int b) {
return a + b;
}
}
This tag can hide java documentation for APIs, Variables, Constructors etc.
Command to generate javadocs:
javadoc Test.java
I am using Weblogic Integration framework. While transforming one XML format to another using .xq file, I want to apply some logic written in a custom Java Class.
For example, XML1 has tag: <UnitCode>XYZ</UnitCode>
Custom Java Class:
public class unitcodemapper{
public static String getMappedUnitCode(String unitCode){
if(unitCode=="XYZ")
return <<value from DB table>>
else
return unitCode;
}
}
XML2 will have a tag: <UnitCode>unitcodemapper.getMappedUnitCode(XML1/UnitCode)</UnitCode>
I cannot find any documentation or example to do this. Can someone please help in understanding how this can be done?
This is known as an "extension function". The documentation for your XQuery implementation should have a section telling you how to write such functions and plug them into the processor. (The details may differ from one XQuery processor to another, which is why I'm referring you to the manual.)
Whilst #keshlam mentions Extension Functions, which are indeed supported by many implementations each with their own API.
I think perhaps what you are looking for instead is Java Binding from XQuery. Many implementations also support this and tend to use the same approach. I do not know whether WebLogic supports this or not! If it does, the trick is to use java: at the start of your namespace URI declaration, you can then use the fully qualified Java class name of a static class, each static method you may then call directly from that namespace.
You can from two examples of implementations that offer the same Java Binding from XQuery functionality here:
http://exist-db.org/exist/apps/doc/xquery.xml#calling-java
http://docs.basex.org/wiki/Java_Bindings
These could serve as examples for you to try on WebLogic to see if it is supported in the same way. However, I strongly suggest you check their documentation as they may take a different approach.
I am using the pluggable annotation processing api withing Java6+ to automatically create some deployment XML files. Part of these XML files contains a description of the object. The description is ALWAYS the same content as the Javadoc associated with the class itself. I could force the comment to be a field of the #Block annotation, but that duplicates the information. Is there any way during annotation processing to get the contents of the class/type comment?
In this example, I want to get "A nice description of my block" during annotation processing.
/**
* A nice description of my block
**/
#Block
public class CustomBlock {
}
I seem to always find the answer right after I post on SO.
For future reference, here is the solution
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.TypeElement;
public class CustomAnnotationProcessor extends AbstractProcessor
{
#Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment re)
{
// use the protected member, processingEnv
String comment = processingEnv.getElementUtils().getDocComment(anyElement);
}
}
The annotation processing API makes use of classes in the javax.lang.model(.*) packages. These model language constructs and said models must be generated during compilation. Since a compiler is intended to ignore comments and documentation, there doesn't seem to be anything in those packages, nor did I expect there to be, that gives you access to comments/doc.
I'm not certain how the javadoc facility performs its work, maybe that can be of help.
Kapep's answer looks interesting, but do mind that it uses stuff from a com.sun.* package, which is implementation-specific. Unless you're absolutely sure that the resources offered to your annotatation processor environment are implemented using those classes and you can safely downcast from the interfaces, it's best not to use that. It'd be a brittle solution at best.
EDIT: as an aside, I'm also using custom annotations + processor to generate metadata in XML format for wiring, validation etc. And I also need descriptions. So what I do is keep the JavaDoc for programming purposes and details that might be interesting to someone directly using the class in code, while having some description key in the annotation (or a default based on class name/other annotation values if none is given) that can be used to obtain a description from some resource file. The description is intended for the "end user" and focuses on high-level stuff, not code specifics. It has the added benefit of facilitating internationalization. I'm not certain this would be of any use to you, but there's my two cents.
There is getDocComment which sounds like it should return the comment.
Update: It got moved to the elements utitlity.
What is the purpose of annotations in Java? I have this fuzzy idea of them as somewhere in between a comment and actual code. Do they affect the program at run time?
What are their typical usages?
Are they unique to Java? Is there a C++ equivalent?
Annotations are primarily used by code that is inspecting other code. They are often used for modifying (i.e. decorating or wrapping) existing classes at run-time to change their behavior. Frameworks such as JUnit and Hibernate use annotations to minimize the amount of code you need to write yourself to use the frameworks.
Oracle has a good explanation of the concept and its meaning in Java on their site.
Also, are they unique to Java, is there a C++ equivalent?
No, but VB and C# have attributes which are the same thing.
Their use is quite diverse. One typical Java example, #Override has no effect on the code but it can be used by the compiler to generate a warning (or error) if the decorated method doesn't actually override another method. Similarly, methods can be marked obsolete.
Then there's reflection. When you reflect a type of a class in your code, you can access the attributes and act according to the information found there. I don't know any examples in Java but in .NET this is used by the compiler to generate (de)serialization information for classes, determine the memory layout of structures and declare function imports from legacy libraries (among others). They also control how the IDE form designer works.
/EDIT: Attributes on classes are comparable to tag interfaces (like Serializable in Java). However, the .NET coding guidelines say not to use tag interfaces. Also, they only work on class level, not on method level.
Anders gives a good summary, and here's an example of a JUnit annotation
#Test(expected=IOException.class)
public void flatfileMissing() throws IOException {
readFlatFile("testfiles"+separator+"flatfile_doesnotexist.dat");
}
Here the #Test annotation is telling JUnit that the flatfileMissing method is a test that should be executed and that the expected result is a thrown IOException. Thus, when you run your tests, this method will be called and the test will pass or fail based on whether an IOException is thrown.
Java also has the Annotation Processing Tool (apt) where not only you create annotations, but decide also how do these annotations work on the source code.
Here is an introduction.
To see some cool stuff you can do with Annotations, check out my JavaBean annotations and annotation processor.
They're great for generating code, adding extra validations during your build, and I've also been using them for an error message framework (not yet published -- need to clear with the bosses...).
The first thing a newcomer to annotations will ask about annotations is: "What is an annotation?" It turns out that there is no answer to this question, in the sense that there is no common behavior which is present in all of the various kinds of java annotations. There is, in other words, nothing that binds them together into an abstract conceptual group other than the fact that they all start with an "#" symbol.
For example, there is the #Override annotation, which tells the compiler to check that this member function overrides one in the parent class. There is the #Target annotation, which is used to specify what kinds of objects a user defined annotation (a third type of construct with nothing in common with other kinds of annotation) can be attached to. These have nothing to do with one another except for starting with an # symbol.
Basically, what appears to have happened is that some committee responsible for maintaining the java language definition is gatekeeping the addition of new keywords to the java language, and therefore other developers are doing an end run around that by calling new keywords "annotations". And that's why it is hard to understand, in general what an annotation is: because there is no common feature linking all annotations that could be used to put them in a conceptual group. In other words, annotations as a concept do not exist.
Therefore I would recommend studying the behavior of every different kind of annotation individually, and do not expect understanding one kind of annotation to tell you anything about the others.
Many of the other answers to this question assume the user is asking about user defined annotations specifically, which are one kind of annotation that defines a set of integers or strings or other data, static to the class or method or variable they are attached to, that can be queried at compile time or run time. Sadly, there is no marker that distinguishes this kind of annotation from other kinds like #interface that do different things.
By literal definition an annotation adds notes to an element. Likewise, Java annotations are tags that we insert into source code for providing more information about the code. Java annotations associate information with the annotated program element. Beside Java annotations Java programs have copious amounts of informal documentation that typically is contained within comments in the source code file. But, Java annotations are different from comments they annotate the program elements directly using annotation types to describe the form of the annotations. Java Annotations present the information in a standard and structured way so that it could be used amenably by processing tools.
When do you use Java's #Override annotation and why?
The link refers to a question on when one should use the override annotation(#override)..
This might help understand the concept of annotation better.Check out.
Annotations when it comes to EJB is known as choosing Implicit middle-ware approach over an explicit middle-ware approach , when you use annotation you're customizing what you exactly need from the API
for example you need to call transaction method for a bank transfer :
without using annotation :
the code will be
transfer(Account account1, Account account2, long amount)
{
// 1: Call middleware API to perform a security check
// 2: Call middleware API to start a transaction
// 3: Call middleware API to load rows from the database
// 4: Subtract the balance from one account, add to the other
// 5: Call middleware API to store rows in the database
// 6: Call middleware API to end the transaction
}
while using Annotation your code contains no cumbersome API calls to use the middle-
ware services. The code is clean and focused on business logic
transfer(Account account1, Account account2, long amount)
{
// 1: Subtract the balance from one account, add to the other
}