Changing package names before building in Bamboo - java

I recently discovered that BlackBerry treats all classes with the same fully-qualified name as identical--regardless of whether they are in entirely different apps or not--causing apps that use different versions of our shared libraries to break when they are installed on the same phone.
To solve this problem, we are planning on changing the package names to include a version number, then building. Can someone explain how, using Bamboo, I can insert a step in our build process that:
changes certain packages names
replaces all code references to the old package name with references to the new package name?

A great tool that is made especially for the task of changing the fully qualified names of Java classes in jar files is jarjar. It can be used easily from within Ant, or alternatively from a shell script.
I have never used Bamboo - I assume, it should work there, too. Of course, there may be some special restrictions in that environment (concerning bytecode manipulation), I don't know about (?)

I'm not familiar with Bamboo and you did not include much information about your build system. If you are using maven, you could use the shade plugin:
This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies.
The second example here shows how to configure package renaming. The resulting jar file would then have to be processed by rapc as in Chris Lerchers comment to his answer. It should be possible to also integrate this in a maven build using the exec plugin.

Related

domain name in default maven package

When I create a Maven project using the quickstart archetype, it populates my src/main/java directory with a default package, "com.domain.my.project_name"
Is there anything that expects me to use this? Will I cause problems by not naming my packages "com.domain.my.project_name.package_name"?
When your project grows enough to be usefull outside of your personal use you may want to publish it to Maven Central, where groupId is required to be unique. Domain name is good in asserting uniqueness. The same applies to Java package names - as soon as they land in classpaths of other people's projects, uniquely naming them is just polite - as is putting them into artifacts with matching groupIds.
If this doesn't seem to apply to your code - you will encounter no problems. But if your project grows and gets opensourced you will face branding issues. Just look at all the confusion caused by org.apache.commons vs commons-io.
Simply put: no. Naming packages like domains is a convention. Nothing forces you to comply to that. Speaking of the Maven archetype: In most archetypes it’s just an example to get you started. If you are unsure about deleting it, use the safely delete action that any good IDE (IntelliJ, NetBeans, eclipse) provides.

figure out how I got a Java package

I am very new to Java. I am running somebody else's program on my computer, and they have imports like:
import weka.classifiers.CostMatrix;
import weka.classifiers.Evaluation;
import weka.classifiers.meta.CostSensitiveClassifier;
import weka.core.*;
The program actually works for me, but I am surprised because weka is a pretty specialized program, so I doubt it is distributed with Java. I never installed weka using any package manager, and I have searched the program code and it doesn't contain any weka packages explicitly.
Do you have any tips for figuring out 1) where these packages are installed, and 2) how I "got" these packages on my local computer? I have read that Java doesn't have a centralized package manager like Python or Perl do, so that might make it harder. I am super new to Java so any basic tips about package management would also be appreciated.
These packages are dependencies of your project, so they have probably been downloaded automatically by a tool that manages dependencies.
There are several possible build tools that can do that. Since you are working with Java/JVM, the usual suspects are Maven and Ant or maybe (less likely) Gradle or SBT.
In your case, the most probable scenario is:
A Maven plugin somewhere in your IDE manages the dependencies and downloads the jars (mvn in console less likely: you would have noticed if you used it)
A pom.xml build definition file lists all the dependencies
A weka dependency is probably declared somewhere in the pom, it should look roughly like this:
-
<dependency>
<groupId>nz.ac.waikato.cms.weka</groupId>
<artifactId>weka-stable</artifactId>
<version>3.8.0</version>
</dependency>
The JARs are stored in a hidden directory .m2 (or maybe .ivy) in your home directory.
The idea is that you can simply get the source code files and the pom.xml, and let Maven (or a similar build tool) download all dependencies, get all the required compiler plugins (or test-coverage tools, or whatever), and build your project. If you tried to do without a build tool, you would have to pass around eternally long lists of dependencies with version numbers that have to be obtained somehow before your program can be compiled, and this would be just a huge mess.
Edit: It is probably downloaded from here: Maven Central: weka-stable
It wouldn't run unless those packages are on the classpath and passed at runtime via
java -classpath
Or you're running an uber JAR file that does contain the libraries.
Common solutions for dependency management include a pom.xml (Maven), build.gradle (Gradle), or build.sbt (SBT).
While those aren't the only options, another solution would be those JAR libraries have been copied into your Java installation somehow

Maven class name collision in Stanford-CoreNLP and Stanford-Parser

My (maven)project is dependent on both stanford-CoreNLP and stanford-Parser and apparently the (lexicalized)parser of each dependency is producing different outputs, they are not alike.
My question is that how can I determine which package the parser should be loaded from ? the parser class has a same name in both packages:
edu.stanford.nlp.parser.lexparser.LexicalizedParser
and maven automatically loads the class from stanford-coreNLP package while I want it to be loaded from stanford-Parser.
I'd appreciate if you please help me with your suggestions.
I would raise a bug asking them to move the lexical parser into a new maven artifact (or several of them), so you can distinguish them.
If that doesn't happen, you have two options:
Use the Maven shade plugin (as suggested by ooxi)
Delete the offending classes
Breakdown of the second approach:
Use you favorite ZIP tool to open the JAR archive.
Delete the offending packages.
Copy the original POM
Change the version version to something like 1.1.MythBuster.1 or 1.1.no-lexer.1
Use mvn file:install to install the modified artifact in your local repo
Test it
Use mvn deploy:deploy-file to install the modified artifact in your company's repo
I prefer the second approach since it makes sure the build has a clean classpath, people know that you messed with the original file and it's pretty obvious what is going on.
I once had this problem and could solve it by using a virtual package depending on the two conflicting dependencies (in your case stanford-CoreNPL and stanford-Parser) and merging them using the Maven shade plugin.
When shading only one class will be in the virtual package, depending on the order of <dependency /> tags.

How to package a library as an eclipse plugin for use by another plugin

I'm trying to build an Eclipse plugin that depends on a library which has to be distributed separate to it. The reasons for that are:
It's a commercial library, while the plugin will be distributed freely. Also, most people won't need it and we don't want to confuse users.
There are currently at least two versions of the library in use and we don't want to build two different versions of the plugin. The interface is compatible, so we can ship just one version of the plugin.
The plugin is for an Eclipse-based development environment and the purpose is to provide our library's functionality within that environment. The library itself depends on other free components, which I can bundle with it without a problem.
Since I don't know if I'm allowed to say exactly which library it is, but I must keep this unambiguous, let's call the library "L" and the plugin I'm trying to develop "P".
I'm using the bnd tool for this and so far I've tried both packaging L as a standalone plugin, and as a plugin fragment.
As a standalone plugin, it was accepted by the host eclipse environment and I could list it as a dependency of P and successfully build that. However, at runtime the P plugin didn't see resources from the L library on its classpath. Mainly those in META-INF/services are needed.
Next, I tried packaging L as a plugin fragment for P. I hoped this would work, since the specs say, that a fragment's classpath is merged with its host plugin's. This didn't work, because I couldn't use the classes from L as build dependencies of P - putting L in eclipse's plugins directory didn't result in it being recognised as an installed plugin.
So I'm stuck. I need L's jars as part of P's runtime and build classpath, while at the same time having them in a separate plugin. Is what I'm trying to do even possible?
For P to have visibility of L's resources, L must export the containing folders as 'packages' and P must import them. This looks a bit inelegant but does allow folders like META-INF/services to be on P's classpath.
Alternatively, for META-INF/services in particular, you could look at new function in release 5 of the Enterprise OSGi spec in the area of ServiceLoaders. A good blog explaining the idea is http://coderthoughts.blogspot.co.uk/2011/08/javautilserviceloader-in-osgi.html, and Apache Aries has an early implementation.
Eclipse plug-in dependencies on other plugins can be defined as Optional. If the user does not have it you can use Class.forName to check if the dependent class has been loaded.
Apparently you didn't list the 'library' plugin as an OSGI import of the 'main' plugin. Without seeing your manifests it's impossible to tell for sure.
As per my understanding,You want to add Jar as plugin dependency.
The best way to do so Go to Plugin View--> Copy your jar file to plugin directory -->Import it as a source project in your workspace.
Plugin.xml-->dependency tab-->add it as a dependency.
If you want to package it in the plugin,use dynamic library loading mechanism.

Is there any disadvantage to putting API code into a JAR along with the classes?

In Java if you package the source code (.java) files into the jar along with classes (.class) most IDE's like eclipse will show the javadoc comments for code completion.
IIRC there are few open-source projects that do this like JMock.
Lets say I have cleanly separated my API code from implementation code so that I have something like myproject-api.jar and myproject-impl.jar is there any reason why I should not put the source code in my myproject-api.jar ?
Because of Performance? Size?
Why don't other projects do this?
EDIT: Other than the Maven download problem will it hurt anything to put my sources into the classes jar to support as many developers as possible (maven or not)?
Generally because of distribution reason:
if you keep separate binaries and sources, you can download only what you need.
For instance:
myproject-api.jar and myproject-impl.jar
myproject-api-src.jar and myproject-impl-src.jar
myproject-api-docs.zip and myproject-impl-docs.zip
Now, m2eclipse - Maven for Eclipse can download sources automatically as well
mvn eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=true
Now, it can also generate the right pom to prevent distribution of the source or javadoc jar when anyone declare a dependency on your jar.
The OP comments:
also can't imagine download size being an issue (i mean it is 2010 a couple 100k should not be a problem).
Well actually it (i.e. "the size) is a problem.
Maven suffers already from the "downloading half the internet on first build" syndrome.
If that downloads also sources and/or javadocs, that begins to be really tiresome.
Plus, the "distribution" aspect includes the deployment: in a webapp server, there is no real advantage to deploy a jar with sources in it.
Finally, if you really need to associate sources with binaries, this SO question on Maven could help.
Using maven, attach the sources automatically like this:
http://maven.apache.org/plugins/maven-source-plugin/usage.html
and the javadocs like this:
http://maven.apache.org/plugins/maven-javadoc-plugin/jar-mojo.html
That way they will automatically be picked up by
mvn eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=true
or by m2eclipse

Categories