Understanding STS: Spring boot application works fine from STS but when gradle is used to build jar, the build fails - eclipse

My spring boot application works fine when run from Spring Tool Suite. However at the time of project deployment when I use Gradle command to build jar file, I get compile error - with error message saying a specific package is missing.
The root cause was that I had missed to add a specific dependency to build.gradle. After adding the missing dependency the build was successful.
Can someone explain how STS was able to refer to the "missing" dependency and able to run the application successfully in development environment?
Is it that STS and Gradle has two different locations where dependencies are stored?

When using STS (or any other IDE for that matter) and you are manually (or through a wizard) adding jars to the classpath entries those will only be available in your IDE.
What you should be doing is adding additional dependencies to your pom.xml or build.gradle (depending on your tooling), which then in turn should be picked up by your IDE again.
NOTE: Some IDEs will automatically detect additions to the classpath and add them to your build files as well. Not sure if STS (and thus Eclipse) does this.

Related

Eclipse/Tomcat publishing unnecessary/problematic dependencies

So first off, a little background.
I am working on converting an Eclipse Java Web Project to Gradle. We use the Vaadin framework and currently manage the project with Ant/Maven/Ivy. We have another project that contains common code that the web project depends on. In both projects our library files, JARs, are simply included in the source and committed to our VCS. With the switch to Gradle we will be using the preferred method of pulling our dependencies from a repository; mainly Maven Central.
I have completed creating the Gradle build scripts that correspond to our current Ant build scripts. I have one Gradle build script for each project, as well as one at the root for configuration injection along with the settings file. I am using the java and eclipse plugins for both projects and additionally the war and vaadin plugins for the web project.
Now to the problem. When I use Gradle to construct the WAR it works perfectly and the WEB-INF/lib directory contains only the JARs that I would expect, based on the dependency configuration. However, when I use Tomcat inside Eclipse to publish the project I end up with a bunch of additional JARs in the WEB-INF/lib directory. Most of the JARs are harmless and just unnecessary, which is why I have excluded them from the WAR, but there are a couple that are actually problematic because Tomcat already has them. In one case it just ignores the JAR and I get the usual message of:
[Tomcat] validateJarFile(*) - jar not loaded.
In the other case I actually receive exceptions in the console, which is troubling even if the application appears to work correctly. I also noticed that all the dependencies associated with the testCompile configuration are also being published, which really doesn't seem right.
The exact offending JARs are tomcat-jdbc and servlet-api-2.5. The tomcat-jdbc JAR is required for compiling our common code. The servlet-api-2.5 JAR is actually just a transitive dependency of vaadin-client-compiler. I have removed the dependency for the vaadin-client-compiler in our web project, because it doesn't appear to be necessary, but it looks like it is still being pulled in by a configuration in the vaadin plugin for Gradle. However, in both cases I am using the providedCompile configuration of the war plugin to exclude them form the WAR.
So my question is, how do I keep Tomcat/Eclipse from publishing these JARs? How do Gradle and Tomcat/Eclipse communicate, or do they at all? From what I can gather it seems that Gradle and Tomcat/Eclipse only communicate indirectly via the .classpath, that the eclipse plugin for Gradle modifies. Also, I have tried the eclipse-wtp plugin for Gradle. It did not seem to resolve the issue because the problematic JARs were still being copied. I am actually not even sure whether I need to use this plugin or if I can just simply use the eclipse plugin.
I should also add that I did install the Gradle Integration for Eclipse "plugin" via the Eclipse Marketplace. With that I used the Configure -> Convert to Gradle Project option that it adds as well as the Gradle -> Refresh Dependencies functionality that it provides. Other than that, I found it to be a little buggy so I've mostly been running Gradle via the command line.
Below is the output of running gradle -v on my machine:
------------------------------------------------------------
Gradle 1.10
------------------------------------------------------------
Build time: 2013-12-17 09:28:15 UTC
Build number: none
Revision: 36ced393628875ff15575fa03d16c1349ffe8bb6
Groovy: 1.8.6
Ant: Apache Ant(TM) version 1.9.2 compiled on July 8 2013
Ivy: 2.2.0
JVM: 1.8.0_05 (Oracle Corporation 25.5-b02)
OS: Mac OS X 10.9.3 x86_64
Please let me know if additional clarification is required. I assume I must be doing something wrong or missing some configuration because surely my scenario is quite common. Many developers use Tomcat inside Eclipse to test web applications locally and with the popularity of Gradle I would be surprised if someone hasn't run into this before. It would seem the main difference with our switch to Gradle, as far as Tomcat/Eclipse are concerned, is that our dependencies are now being loaded from a repository instead of being linked directly in the source.
Any help is greatly appreciated.
However, when I use Tomcat inside Eclipse to publish the project I end up with a bunch of additional JARs in the WEB-INF/lib directory. Most of the JARs are harmless and just unnecessary, which is why I have excluded them from the WAR, but there are a couple that are actually problematic because Tomcat already has them.
This is a known problem with the gradle eclipse tooling. The problem is that it doesn't understand about dependencies with 'provided' scope. See this issue for some details:
https://issuetracker.springsource.com/browse/STS-2380
There is a workaround for this problem. Some common dependencies that 'cause problems' can be globally excluded via a list of regexps you specify in the preferences. Open menu "Window >> Preferences >> Gradle >> WTP". That's where you can add regexps that will be used to exclude jars from the 'deployment assembly'.

JUnit test fails with java.lang.ClassNotFoundException: com.mysql.jdbc.Driver on Tycho environment

I have a very strange situation. I have a set of eclipse plugin projects which I am using tycho and maven for building them. I used JDBC driver in one of the projects and I have a test plugin to test this project. Since the com.mysql.jdbc plugin was not available in the eclipse p2 repository ( and we don't have our own p2), I imported the jdbc plugin and created an OSGi plugin and add the dependency to my local plugin.
I have multiple eclipse workspaces sat up. Only in the very first workspace that created the test and jdbc plugin, junit tests are working when I run them using eclipse run as -> Junit test command. When others or even me checkout the source codes and try to run the test in different workspaces, this exception is thrown:
java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
I also tried using tycho integration test (runing mvn integration-test) but that doesn't work neither and I still get the same exception. I tried searching for this a lot but I couldn't find the answer.
UPDATE:I think it is not a tycho problem. I just tried to create the eclipse plug in based on com.jdbc.mysql jar. The workspace I created this on is working fine. But as soon as I commit the code and import the project in another workspace the tests stop working. All of the settings are same among two workspaces, one is working the other gets the ClassNotFound exception!
Tycho computes the OSGi runtime based on the transitive dependencies of your test bundle.
You probably have no design-time dependency on the mysql driver bundle (but rather only on the JDBC interfaces it implements)
Try adding a test runtime dependency on the mysql jdbc driver bundle.
See http://wiki.eclipse.org/Tycho/FAQ#How_to_add_a_undeclared_dependency.3F__.28e.g..2C_OSGi_declarative_service.29 on how to do this.
ClassNotFoundExceptions in an OSGi runtime indicate that there is something wrong in the imports and/or export declarations in the OSGi manifests. The most frequent case is that a bundle claims to export a certain package, but doesn't actually have the binaries/class files of that package.
In a Tycho build, this can easily happen if you don't have the entry . in the bin.includes property in the build.properties.

How to force eclipse to republish project when changing source in another module

I have multi module maven project.
One of the modules is actual web application, the JBoss is the server.
Other subprojects are dependencies for the web project.
I am running it in JBoss embedded in eclipse. Pretty straightforward configuration.
When executed from within eclipse, if I do mvn clean, mvn package - then clean + publish to JBoss, everything works wonderfully.
If I change source code for the web project, eclipse detects the need to republish automatically and does job well.
However if I change source in the non-web subproject, eclipse does not detect change and I have to mvn clean, mvn package, then publish to JBoss manually for it to pick the code change.
This is annoying since packaging job takes about a minute, then publishing job takes another 30 seconds. I have to clean since simply packaging without clean does not pick the change either.
Is there a way to configure things in the eclipse so that any source change in any subproject/module is automatically recognized by eclipse and it would republish to JBoss upon selecting "run"?
There is another bad side effect - debugging of the source that is not web project is impossible - eclipse's debugger does not see that source. It sees only source of the web module.
Thanks,
Nikolay
Make sure that your web project has dependencies on the other modules(projects) defined in the pom and in the eclipse project. you can check that in the build settings. If they are not there then it probably means that the project file was not generated from your maven .pom file. You can generate that by running
mvn eclipse:eclipse

JUnit uses wrong Base64

I wanna use the class Base64 from commons-codec 1.5 and when I run the code on Server this works fine. My application runs on Websphere 7.0.
But when I run my JUnit tests the wrong Base64 Class is choosen, when i ask the Class with:
System.out.println(Base64.class.getProtectionDomain().getCodeSource().getLocation());
the output is: file:/C:/EProg/IBM/SDP80/runtimes/base_v7/plugins/com.ibm.ws.prereq.soap.jar
Thats definitly the wrong Version.
And an error occurs because of the wrong Version:
java.lang.NoSuchMethodError:
org/apache/commons/codec/binary/Base64.decodeBase64(Ljava/lang/String;)
The crazy thing is, that happens only it i choose one Test and run it with Run As: JUnit Test in Eclipse, if I run the whole thing with Maven everthing works fine.
I use JUnit 4.8.1 and Eclipse Indigo Service Release 2 with some Plugins for Websphere, GWT and Maven.``
com.ibm.ws.prereq.soap.jar is an OSGi bundle, and in WebSphere (which is built on an OSGi container), the classes in org.apache.commons.codec.binary are not visible to applications because that package is not exported by the OSGi bundle (you can examine the list of exported packages by looking at the META-INF/MANIFEST.MF file in com.ibm.ws.prereq.soap.jar). That explains why you don't encounter any issue when running your application in WebSphere.
On the other hand, when you add that JAR to a Java project in Eclipse, it will be treated like a simple JAR, not an OSGi bundle, and all packages will be visible. In your case this creates a conflict with another commons-codec dependency.
I guess that the reason why you don't encounter that issue in Maven is that com.ibm.ws.prereq.soap.jar is only a dependency of your Eclipse project, but not of your Maven project.
Unfortunately there are not many (simple) ways to solve that issue. One is to remove com.ibm.ws.prereq.soap.jar from your Java project (I doubt that you are actually using Apache SOAP). The other is to change the order, so that your other commons-codec dependency comes before com.ibm.ws.prereq.soap.jar.
It looks like a class path issue. More precisely, Eclipse integration with Maven. I would investigate Eclipse dependencies and make sure that it uses Maven for dependency management.
You can do it in two ways, either you can run mvn eclipse:eclipse command or use M2Eclipse plugin. If you use the later, then there is a update dependency option, in the project context menu.

Why does eclipse not find the beans.xml files in a spring based Maven project

I have a maven project under eclipse with m2eclipse.
WHen running integration tests the tests fail with the mention that the spring configuration files cannot be found on the classpath, and I get a similar error from log4j.
I was under the impression that m2eclipse would add the resources directories to the classpath but apparently not.
What am I doing wrong?
sometimes m2eclipse doesn't move resources as required. I haven't really figured out why. Anyway: a simple solution is to keep a shell open and do
mvn resources:resources
or in m2eclipse, create a new run configuration using Run Configurations -> Maven Build -> new Launch Configuration setting goals to: either process-resources (lifecycle) or resources:resources (plugin goal).