Strategies for mixing in the gwt compatible and non compatible source - java

Yes i know one alternative to solving this problem is simply to create two source directories from the original. The class path for the GWT compiler would thus be setup to simply only see the compatible source while both would be used for the server portion of your app.
Firstly i find this kind of ugly, because it means i now have two source directories with potential doubles of classes.
refactoring and other structural abilities of the IDE can potentially be problematic as it will get confused.
Sometimes its not possible to put some stuff in separate packages: think client and server packages simply because one would then have to make something public which should really be package private to limit scope accessibility.
is there a library that enables classes or methods to marked as ignored by the GWT compiler ?
Is there a better way ?

You can exclude classes (files actually) from GWT's source path using Ant-like includes/excludes: http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuidePathFiltering
You cannot exclude methods or inner classes though, it really is file-based. See http://code.google.com/p/google-web-toolkit/issues/detail?id=3769

Make a shared directory that has the code that both the GWT side and server side can read. Any classes that would be duplicated instead go into this folder, to be accessed (without duplication!) from both client- and server-sides of your app.

Related

Two JARs on buildpath with identical method names but different constructors. How can I specify which JAR's method to use?

I am building a tool from several different open source libraries. My buildpath is in the following order:
My first JAR file, stanford-corenlp-3.3.0.jar, contains a package called edu.stanford.nlp.process, which has the Morphology.class class.
My second JAR file, ark-tweet-nlp-0.3.2.jar, contains an identical package name (edu.stanford.nlp.process), and an identical class name Morphology.class.
In both JARS, inside their respective Morphology classes there exists a method called stem(). However, the constructors for these methods are different. I want to use the stem(String, String) method from my second JAR file, but since the import statement (import edu.stanford.nlp.process.Morphology;) does not specify which JAR to use, I get an error since it thinks the first JAR on the buildpath is the one I want to implement.
I don't want to change the order of my buildpath since it would throw off my other method calls.
How can I specify which JAR's Morphology class to use? Is there an import statement that specifies the JAR, along with the package.class?
EDIT: What about a way to combine my two JARs so that the two Morphology classes merge, giving me two methods with different constructors?
As several others pointed out above, it is possible to tweak Java's classloader mechanism to load classes from certain places… but this is not what you are looking for, believe me.
You hit a known problem. Instead of worrying how to tell Java to use a class from one JAR and not from the other, you should consider using a different version of ArkTweet.
Fetch the ArkTweet JAR from Maven Central. It does not contain Stanford classes.
When you notice that people package third-party classes in their JARs, I'd recommend pointing out to them that this is generally not a good idea and to encourage them to refrain from doing so. If a project provides a runnable fat-jar including all dependencies, that is fine. But, it should not be the only JAR they provide. A plain JAR or set of JARs without any third-party code should also be offered. In the rare cases that third-party code was modified and must be included, it should be done under the package namespace of the provider, not of the original third-party.
Finally, for real solutions to building modular Java applications and handling classloader isolation, check out one of the several OSGi implementations or project Jigsaw.
The default ClassLoader will only load one of the jars, ignoring the second one, so this can't be done out of the box. Maybe a custom ClassLoader can help.
For more info about ClassLoaders start from here.
Good luck!
EDIT: We are looking at some horrible packaging choices causing as side effect this Jar Hell here. The author of this "Ark Twitter" library decided it was a good idea to release a JAR artifact that includes a third party library (the Stanford NLP library). This leads to unnecessarily tight coupling between Ark Twitter and the specific version of the Stanford NLP library used by it. This is a very bad practice that should be discouraged in any case: this violates the whole idea about transitive dependencies.
EDIT (continued): One possible (and hopefully working) solution is to rebuild the Ark Twitter JAR so that it does not include the aforementioned library but only its own code (basically the cmu.arktweetnlp package only) and hoping that the version of NLP required by your project works with Ark Twitter. Ideally you should submit a pull request to the author of the library but in the meantime you can get away with un-jarring and re-jarring the existing JAR file.
EDIT 2: Looking at the JAR file again, it's much worse that I originally thought: ALL the dependencies are repackaged in the released JAR file. This is really the worst possible solution for releasing a library. Good luck.
I think your problem can be solved simply by using the lemma(String word, String tag) method in the current CoreNLP's Morphology class:
String word = ...;
String tag = ...;
String lemma = morphology.lemma(word, tag);
WordTag wt = new WordTag(lemma, tag);
When the class was revised a couple of years ago, the method you're looking for was deleted. The feeling was that with most of the Stanford NLP code moving to using CoreLabels, methods that return WordTag are less useful (though deleting all such methods is still a work in progress).
No there isn't. This is a weakness of Java, that cannot be simply solved. You should use only one of the libraries. Having both on the classpath will make java always select the first one.
This problem is named as Jar hell.
The order in the buildpath generally determines the order in which the classloader will search for the class. In general, though, you don't want duplicates of the same class in your build path--and it sure doesn't seem like ark-tweet-nlp-0.3.2.jar should have a edu.stanford package within it.
When you load a class, it's loaded at given address, and that address is then placed in the header of objects created from the class, so that (among other things) the methods in the class can be located.
So if you somehow load ClassA, with method abc(String), from zip file XYZ.zip, that loads into address 12345. Then (using a class loader trick) you load another ClassA, with method abc(String, String), from zip file ZYX.zip, and that loads into address 67890.
Now create an instance of the first ClassA. In its header will the class address 12345. If you could somehow attempt to invoke the method abc(String,String) on that class, that method would not be found in the class at 12345. (In actuality, you will not even be able to attempt the call, since the verifier will stop you because, to it, the two classes are entirely different and you're trying to use one where the other is called for, just as if their names were entirely different.)

Java - make a library and import optional

I have a library that I'm using in an Java application - it's important for certain functionality, but it's optional. Meaning that if the JAR file is not there, the program continues on without issue. I'd like to open source my program, but I can not include this library, which is necessary to compile the source code as I have numerous import statements to use the API. I don't want to maintain two code sets. What is the best way to remove the physical jar file from open source release, but still maintain the code to support it where other people could still compile it?
the typical approach taken is to define the wrapper API (i.e. interfaces) and include those interfaces in the open sourced code, and then provide configuration options where one can specify class names of classes that implement certain interfaces.
You will import API interfaces instead of importing classes directly into your open sourced code. This way, you are open sourcing the API but not the implementation of the parts that you do not want to open source or you cannot open source.
There are many examples, but take a look at JDBC API (interfaces) and JDBC drivers (implementation classes) for starters.
I was pretty much typing the same thing as smallworld with one addition. If this API were necessary you can use a project build tool like Maven to handle the dependencies on you project. If someone checks it out from source control with the pom they can download the dependencies for themselves and you don't have to include them in a source repo.
There's probably a number of ways to fix this, here's a couple I can think of:
If you have only a couple of methods you need to invoke in the 3rd party library, you could use reflection to invoke those methods. It creates really verbose code, that is hard to read though.
If you don't have too much of the API in the 3rd party library you use, you could also create a separate JAR file, containing just a non-functional shell of the classes in the library (just types with the same names and methods with the same signatures). You can then use this JAR to distribute and compile against. At run-time you'd replace it with the real JAR if available.
The most common way is probably to just create a wrapper API in a separate module/project for the code that is dependent on the 3rd party library, and possibly distribute a pre-built JAR. This might go against your wish to not maintain two code sets, but may prove to be the best and less painful solution in the long run.

Java files on the same folder and on the same package

At least on my machine when I put 2 Java class files on the same folder, without making them part of the same package, they already see one another, so from one file I can call a public class from the other file and vice-versa.
Questions:
Is this the general case or a coincidence that may not work on every platform?
If this is not a coincidence, I am guessing the purpose of packages is to allow you to organize your class files and make they share stuff, even if they are spread across different folders and paths. Is this correct or I am missing something?
If no package name is specified, the classes in the file go into a special unnamed package. And this is the same case for all files with no explicit package specification. Hence, they all fall into the special unnamed package, and exhibit the behavior that you are seeing.
You might want to go through this for a better understanding.
If they're in the same directory then they're in the same package, or are you copying .class files around after they've been written by the compiler?
Packages are a way of organising classes into a namespace. There are plenty of reasons to do this, the best bet is to start with the tutorial.
I sure it is general case, but it is bad approach.
You are right, but more general reason to use package is to separate namespaces, for example, you have to create Car class, but there are many people who want to use this classname, thats why you have to use package, for example: com.yourcompany.yourproject. In such case you can use your Car class from your package without implicitly defining package and you also can use other Car classes in such manner: new com.google.general.Car();
In the java rules, it is recommend to use domain name right-to-left for providing unique package name.

Java package politics

I always doubt when creating packages, I want to take advantage of the package limited access but at the same time I want to have similar classes divided into packages.
The problem comes when you understand that packages are not hierarchical in Java:
At first, packages appear to be
hierarchical, but they are not.
source
Imagine I have an API defined with its classes at foo.bar, only the classes the API client needs are set public. Then I have another package with some internal objects I need in the API defined at foo.bar.pojos, this classes need to be public so they can be accessed by foo.bar but this means the API client could also access them if the package foo.bar.pojos is imported.
What is the common package politic that should be followed?
I've seen two ways of doing.
The first one consists in separating the public API and internal classes into two different artefacts (jars). The documentation is separated as well, and it's thus easy for the end user to make the distinction between what is internal and what is not. But it sometimes make things more complex to have two jars, two source trees, etc.
The second one consists in delivering a single jar, but have a good documentation allowing to know what's internal and what's not. The textual documentation can explain how to use the API (and thus avoids talking about the internals). And the javadoc can specify that a class is for internal use and is thus subject to changes.
Yes, Java packages don't give you enough control over your dependencies. The classic way to deal with this is to put external APIs in one package and internal implementation classes in another, and rely on people's good sense to avoid creating dependencies on the latter.
With Maven and OSGI, you have an additional mechanism for managing dependencies between modules / bundles of packages. In the case of OSGI, you can explicitly declare some packages as not exported, and an OSGI aware development environment will prevent people creating harmful dependencies. Maven's module support is weaker, but at least it controls dependency cycles.
Finally, you could use custom PMD rules to enforce your project's modularization conventions ... in the same way that there are rules to discourage dependencies on Java's "com.sun.*" package tree.
It is a mess.
Using only what Java itself offers, you have to put everything in the same package. You end up with a single (or a few) packages with lots of classes, and no good way to group them for yourself (but at least that problem does not leak outside). Most people don't do that, though, and as a result, your (as a developer on top of these libraries) public classpath is littered with stuff you should never need to see.
You might like OSGi, which has (and enforces) the concept of bundle-private packages. Those are not exported to the outside world.

hide some class file or package in jar file

How can I export a jar without some class or package which I don't want others to use,but which is needed in project,means I can't delete them.
This doesn't make a lot of sense.
If the classes are needed to compile the project, then there are likely to be static dependencies on them in other classes. (Otherwise ... you would be able to just delete it / them.)
But if there are static dependencies on those classes, then you won't be able to run the applications unless those classes are present in the JAR file. If you leave the classes out of the JAR to stop people using them (or whatever), your application will die on startup with "class not found" exceptions.
If you want to stop people using the classes directly, you could try the following:
Change the classes access to "package private". This doesn't make it impossible to use them, but it makes it more difficult.
Change your project so that the dependencies on the classes are entirely dynamic; e.g. via Class.forName(...) or dependency injection. Then you can exclude the classes from the JAR as required. But once again, if your application needs to use the classes, they have to be accessible at runtime (somehow), and it will therefore be possible (somehow) for other people to get hold of them.
Change your project to allow you remove the classes entirely. This is the only sure-fire solution.
Finally, before you go to all of this trouble you should ask yourself why you are even bothering to do this. Why don't you just let people use the classes anyway? What is to stop them getting the classes from somewhere else ... or implementing their own versions from scratch?
If the class is needed for your program to work, you can't omit it from the JAR.
You can put classes in a package that has something like "internal" in its name — e.g. com.example.internal — to indicate that the classes aren't meant for others to use or rely on. It can't prevent anyone from using your class for their own purposes, but it at least indicates that they do so at their own risk, that your internal interfaces might change in future versions of the program, etc.
A simple way is to use the package private access modifier for classes. That will make it difficult for others to access the classes, but it will also affect your ability to use them from other packages.
A more advanced way would be to use OSGi and only publish those classes you want others to use. That will make it impossible for others to access the classes while not restricting your access to them.
Put them into a separate jar file, include that jar file (as a single file, maybe with a nondescript name) into your jar file, create a custom class loader to open that embedded jar file from your code, bootstrap an entry point with reflection (because you cannot have static dependencies on it) into that new class loader .
Or just accept the fact that since the code is in there somewhere, any amount of obfuscation is just an inconvenience to everyone and cannot really hide anything.

Categories

Resources