I'm new to threading in java and now read the "java concurrency in practice". As you possibly understand I'm trying to do any examples but can't. when I'm trying to use #Immutable annotation IDE(Idea) underlines it red.
What is the possible reason of this?
The reason is that you do not have the correct jar in your classpath.
The maven artifact for this jar is:
<dependency>
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<version>1.0</version>
<dependency>
If you do not have this jar in your classpath, you don't have the annotation.
Note however that this is superseded by JSR 305. There is also a Maven artifact for an implementation of that JSR:
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>2.0.1</version>
</dependency>
(side note: excellent choice of a read! This is one must-have book for all Java devs out there)
Download the jar file providing the jcip annotations and add it to the module dependencies.
As far as working with that book's examples, so all those annotations, like #ThreadSafe, #Immutable/#Threadsafe, they all are just symbolic (though fge above is correct, you can use those jars as well, but from learning perspective, just ignore them)
So, simply ignore them. Anywhere, if you see #Immutable, it simply means that code written is IMMUTABLE, by the virtue of code implementation.
You don't need any jar at all. Just remove those annotations from your examples :)
Related
I'm working off an AEM project, I'm new to AEM btw. I'm trying to use a couple of 3rd party non-OSGI libraries, like Dozer and Spring. I'm really struggling with this, it is a pain in the ass, maybe it is because OSGI is kind of old school. My bundles get installed, but not Active in the OSGI console, as they complain about missing packages.
I want to do step by step. First I want to make work my bundles with just Dozer and nothing else. This is my pom dependencies:
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer-osgi</artifactId>
<version>5.5.1</version>
</dependency>
Here is my maven-bundle-plugin configuration:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<version>4.1.0</version>
<configuration>
<instructions>
<Export-Package>somepackages*</Export-Package>
<Private-Package/>
<Import-Package>*</Import-Package>
<Sling-Bundle-Resources>/META-INF</Sling-Bundle-Resources>
</instructions>
</configuration>
</plugin>
As you can see, I'm using dozer-osgi already. I'm not sure why it doesn't pick it up. It complains about this:
org.dozer,version=[5.5,6) -- Cannot be resolved
org.dozer.loader.api,version=[5.5,6) -- Cannot be resolved
First, I don't understand why it says [5.5,6), because I'm telling it to use 5.5.1. Second, I'm using dozer-osgi already, I believe it should pick it up automatically.
I tried also using:
<Embed-Dependency>dozer-osgi</Embed-Dependency>
Whit dozer-osgi added, things start to get better, and more complex at the same time. It seems like now it loads dozer, but starts complaining about transitive dependencies:
android.dalvik -- Cannot be resolved
dalvik.system -- Cannot be resolved
javassist.util.proxy -- Cannot be resolved
org.apache.commons.beanutils,version=[1.9,2) -- Cannot be resolved
org.apache.commons.beanutils.converters,version=[1.9,2) -- Cannot be resolved
The beanutils utils is easy to fix. I just need to add the regarding dependencies like this:
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
</dependency>
and add "commons-beanutils" here:
<Embed-Dependency>dozer-osgi,commons-beanutils</Embed-Dependency>
Now, it complains about:
android.dalvik -- Cannot be resolved
dalvik.system -- Cannot be resolved
javassist.util.proxy -- Cannot be resolved
org.hibernate.proxy -- Cannot be resolved
The hibernate dependency error is new. I thought beanutils depended on hibernate, but not, is Dozer the one depending on it.
I tried adding hibernate, like this:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.9.Final</version>
</dependency>
<Embed-Dependency>dozer-osgi,commons-beanutils,hibernate-core</Embed-Dependency>
And so on, it is like a look, it gets worse and worse everytime I try to add a transitive dependency. I also tried this, only keeping dozer-osgi in my dependencies:
<Embed-Dependency>dozer-osgi</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
Result:
android.dalvik -- Cannot be resolved
dalvik.system -- Cannot be resolved
javassist.util.proxy -- Cannot be resolved
org.hibernate.proxy -- Cannot be resolved
org.apache.commons.beanutils -- Cannot be resolved
org.apache.commons.beanutils.converters -- Cannot be resolved
It is like if Embed-Transitive doesn't work at all.
What is the best way to work with 3rd party libraries when using Maven and AEM? In my case, Maven is using to install the bundles in my AEM instance.
In OSGi you have to distinguish between the build and the runtime. At build time your initial approach was totally fine.
You use dozer and the maven-bundle-plugin creates suitable Import-Package statements. You can check these by looking into the Manifest of the jar.
The rules for package imports result in a range of version that should work with your code. So [5.5,6) is exactly the expected import range.
Now to runtime. Here you have to supply all dependencies of your code (including the transitive ones) as bundles in AEM (or more generally in the OSGi runtime).
So you also need to install dozer OSGi as bundle. If this complains again then you also need to install its dependencies.
This is the default approach and normally totally fine.
Now if you want to make your bundle standalone in respect to having no additional runtime depenencies then you can try to embed all dependencies. Then you only need to install your bundle.
Be aware though that this is not easy. If your code uses some of the embedded classes in its own API then you get into lots of problems with embedding. So if your are not very experienced then better go the way of installing all dependencies as bundles.
To simplify the install process you can create a content package that contains all needed bundles.
You also have to check that all dependencies actually are bundles. In some cases the normal maven dependencies are not suitable. In this case have a look at apache servicemix bundles. It is a project that creates OSGi bundles for popular dependencies and deploys these to maven central.
Please help,
For the past couple of days I have been trying to get Logback 1.1.3 to work with my Bukkit plugin. For reference my pom.xml includes these lines:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.3</version>
</dependency>
And the following jars are listed under "Maven Dependencies":
logback-core-1.1.3.jar
logback-classic-1.1.3,jar
slf4j-api-1.7.7.jar (which appeared out of nowhere)
The stacktrace that the server console produces can be found here (line 29 of MoneyDrops.java is:
private static final Logger LOGGER = LoggerFactory.getLogger("MoneyDropsLogger");).
I have also searched through stackoverflow but all the answers suggest that I need to provide an implementation that use the SLF4J api (such as log4j), however, it is to my understanding that logback natively implements the api and that I do not need another jar file.
Any help would be greatly appreciated.
There's a dependency in the pom of logback-classic to slf4j which Maven will resolve. That's the reason of the "appeared out of nowhere".
If I read the documentation of JavaPluginLoader it says:
Represents a Java plugin loader, allowing plugins in the form of .jar
I'm not at all familiar with this library but I would interpret it as "This plugin will only load the specified jar" which would be the MoneyDrops jar.
Line 127 at https://github.com/Bukkit/Bukkit/blob/master/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java actually provides the bukkit classloader and a file as the classpath. I presume the file will be your jar.
So in order to make this work you'd need to somehow make your dependencies available to the classloader of bukkit. Maybe the minecraft server?
Another option is to unpack all the dependencies. The jars are compressed files anyway and repack them with your code. This way you can provide a single jar to the pluginloader. There's a maven plugin doing this for you but I forgot the name.
Thank you all for your help! I have concluded that I do not actually need logging in my plugin anyway (it is not that heavy) and have opted to remove it completely and rely on the Bukkit logger instead. Again, thank you all for your help.
I'm developing an application that will be used internally at our company. In order for it to interop with our other internal systems I have to use some maven dependencies that we use internally, but this is causing some issues with using some external 3rd party dependencies that I also need.
So essentially my pom looks like this:
<dependencies>
<dependency>
internal-framework-artifact
</dependency>
<dependency>
necessary-third-party-artifact
</dependency>
</dependencies>
I've come to find that both of these dependencies have the apache's commons-collections as one of their own dependencies (among a large number of others, but we'll just keep it at one for this question's simplicity).
If I place exclusion rules on both of them for the commons-collections pom I can compile the project, but my resulting jar won't have access to either version of commons-collections and will just result in a java.lang.NoClassDefFoundError exception. Removing the exclusion rule on either of them just results in a mvn compiler error:
[WARNING] Rule 2: org.apache.maven.plugins.enforcer.BanDuplicateClasses failed with message:
Duplicate classes found:
I've been looking through various so q/a's and I can't really seem to find something that's 100% relevant to my situation. I'm really at a loss as to how to resolve this. Am I missing something really obvious?
I've never actually used the maven-shade-plugin for shading, but I think this is the exact use case it was designed for.
Create a new project that uses the maven-shade-plugin (see: http://maven.apache.org/plugins/maven-shade-plugin/) to produce an uber-jar version of internal-framework-artifact which contains that classes in internal-framework-artifact and all its dependencies. Configure the plugin so that it relocates all the classes that are also dependencies of necessary-third-party-artifact to some non-conflicting package names. This new project should produce a .jar with a different name, something like internal-framework-artifact-with-dependencies.
Now modify your original pom so that it is dependent on internal-framework-artifact-with-dependencies instead, and it should work.
Say I have this dependency in my pom.xml file:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
</dependency>
When I do a
clean install
all the javaee-api-6.0.jar will be included in the war file under WEB-INF\lib folder.
Is it possible that instead of including the whole jar, only classes that I use and their dependencies are included?
If you're deploying into a Java EE application server, that entire JAR is already provided by the application server, and can be omitted from the WAR file. You can accomplish this by putting it into the provided scope:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
That makes that dependency available for compilation and test execution, but will not package it into the WAR.
In contrast, trying to determine which individual classes you need so you can only include their class files is an ultimately pointless endeveor. The JVM only loads classes when they are used - that is, unused classes are not loaded.
It is generally impossible to identify the used classes at compile time due to reflection. For instance, consider:
System.console().printf("Please specify the implementation class to use");
String className = System.console().readLine();
FooService service = (FooService) Class.forName(className).newInstance();
service.work();
You can get the JVM to log which classes are loaded, but different executions can use different classes ...
It's not a viable option - at least not in maven, although You know which classes You are using, but You don't know what are the dependencies for each class that You imported - so it might be impossible satisfy it's requirements. This is why we are using tools like maven - to ease the process importing a library.
Read some more about reduce size of built project and see what are Your options there
Except for UberJAR, Your biggest chance (IMHO) would be to identify libraries that are provided by the container, and use provided scope for them.
You also could integrate 3rd party tools like ProGuard
You could use exclusions.
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<exclusion>
<groupId>...</groupId>
<artifactId>...</artifactId>
</exclusion>
</dependency>
But I don't think you could exclude at class-levels. This only excludes dependencies useful when there are conflicting dependencies in your project.
It is really not a viable option in my opinion ,as its almost impossible to know internals what all classes are required at runtime until and unless you are seeing the,implementation of all the,3rd part apis that you are using.
I also think the whole idea behind the maven is to ease the development and build process so that you won't have to do any effort in identifying the artifacts that are required at runtime or compile time. Maven will automatically figure out that for you.
I am getting this exception while trying to call SOAP webservice using axis. basically I have written a axis client.
org.apache.commons.discovery.DiscoveryException: Class org.apache.commons.logging.impl.SLF4JLogFactory does not implement org.apache.commons.logging.LogFactory.
When I remove the all the common-logging jars, I would able to remove these errors but these jars are coming from other apis, i dont have control on them.
Is there any way to overcome this problem?
There is a pretty detailed explanation of what the issue may be and ways to debug it in the commons logging documentation. Your particular issue may be,
There is also another more unusual way in which this cast can fail:
even when the binary is compatible, the implementation class loaded at
runtime may be linked to a different instance of the LogFactory class.
For more information, see the tech guide.
None of this solutions worked for me. I figure out my solution in SLF4J documentation
http://slf4j.org/faq.html#excludingJCL
alternative 2) provided scope Commons-logging can be rather simply and
conveniently excluded as a dependency by declaring it in the provided
scope within the pom.xml file of your project. The actual
commons-logging classes would be provided by jcl-over-slf4j. This
translates into the following pom file snippet:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.21</version>
</dependency>
The first dependency declaration essentially states that
commons-logging will be "somehow" provided by your environment. The
second declaration includes jcl-over-slf4j into your project. As
jcl-over-slf4j is a perfect binary-compatible replacement for
commons-logging, the first assertion becomes true. Unfortunately,
while declaring commons-logging in the provided scope gets the job
done, your IDE, e.g. Eclipse, will still place commons-logging.jar on
your project's class path as seen by your IDE. You would need to make
sure that jcl-over-slf4j.jar is visible before commons-logging.jar by
your IDE.
SLF4J documentation gives more alternatives, this worked for me.
The Link to the above mentioned Documentation to section "Fixes" suggests to include
-Dorg.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
in your setup.
For some people it might be easier to include this code instead:
static
{
System.setProperty(LogFactory.FACTORY_PROPERTY, LogFactory.FACTORY_DEFAULT);
}
Replace jcl-over-slf4j jar with commons-logging jar
Probably its too late :-) but for me following worked. I am using spring boot and added it as first line in the main methods. More explanation as suggested above is here.
System.setProperty("org.apache.commons.logging.LogFactory", "org.apache.commons.logging.impl.LogFactoryImpl");