AspectJ with jar classloader - aspectj

I am trying to instrument Oracle Rest Data Service (ORDS) which is built on Jetty. The aspect should trace JDBC calls. I do not see the weaving happening.
I have tried AspectJ in a different standalone application which used JDBC and also profiled Servlet calls in an application running in standalone Jetty and all this worked for me. But in this case there is an exception and it does not look that weaving is happening. Application itself works as expected with all AspectJ configurations applied.
Two options have been tried:
aspect class and aop configuration file were put into jar and this jar was placed inside WEB-INF/lib. aspectjrt.jar was copied into this directory as well.
the aspect class and aspect config were copied into WEB-INF/classes
like this
├── WEB-INF
│ ├── beans.xml
│ ├── classes
│ │ ├── META-INF
│ │ │ ├── MANIFEST.MF
│ │ │ └── aop-ajc.xml
│ │ └── WhereTheStatementTimeGo.class
There was an exception like below in both cases.
Here is the command line and the exception:
$JAVA_HOME/bin/java -javaagent:/DATA/PROJECTS/ASPECTJ19/lib/aspectjweaver.jar -Dorg.aspectj.tracing.enabled=true -Dorg.aspectj.tracing.factory=defaug.aspectj.tracing.messages=true -jar ords.war standalone
[JarClassLoader#17f052a3] warning parse definitions failed -- (IllegalStateException) sun.misc.Launcher$AppClassLoader#18b4aac2
sun.misc.Launcher$AppClassLoader#18b4aac2
java.lang.IllegalStateException: sun.misc.Launcher$AppClassLoader#18b4aac2
at oracle.dbtools.jarcl.NestedResourceHandler.jarClassLoader(NestedResourceHandler.java:36)
at oracle.dbtools.jarcl.NestedResourceHandler.openConnection(NestedResourceHandler.java:23)
at java.net.URL.openConnection(URL.java:979)
at java.net.URL.openStream(URL.java:1045)
at org.aspectj.weaver.loadtime.definition.DocumentParser.saxParsing(DocumentParser.java:157)
at org.aspectj.weaver.loadtime.definition.DocumentParser.parse(DocumentParser.java:123)
at org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.parseDefinitions(ClassLoaderWeavingAdaptor.java:290)
at org.aspectj.weaver.loadtime.DefaultWeavingContext.getDefinitions(DefaultWeavingContext.java:130)
at org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.initialize(ClassLoaderWeavingAdaptor.java:174)
at org.aspectj.weaver.loadtime.Aj$ExplicitlyInitializedClassLoaderWeavingAdaptor.initialize(Aj.java:337)
at org.aspectj.weaver.loadtime.Aj$ExplicitlyInitializedClassLoaderWeavingAdaptor.getWeavingAdaptor(Aj.java:342)
at org.aspectj.weaver.loadtime.Aj$WeaverContainer.getWeaver(Aj.java:316)
at org.aspectj.weaver.loadtime.Aj.preProcess(Aj.java:108)
at org.aspectj.weaver.loadtime.ClassPreProcessorAgentAdapter.transform(ClassPreProcessorAgentAdapter.java:51)
at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at oracle.dbtools.jarcl.JarClassLoader.findClass(JarClassLoader.java:77)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at oracle.dbtools.jarcl.Entrypoint.invoke(Entrypoint.java:50)
at oracle.dbtools.jarcl.Entrypoint.main(Entrypoint.java:77)
2019-07-02 16:47:29.822:INFO::main: Logging initialized #3375ms to org.eclipse.jetty.util.log.StdErrLog
Jul 02, 2019 4:47:29 PM
INFO: HTTP and HTTP/2 cleartext listening on port: 8080
Jul 02, 2019 4:47:29 PM
INFO: Disabling document root because the specified folder does not exist: /Users/slinetsk/Downloads/ORDS/ords/standalone/doc_root
2019-07-02 16:47:30.632:INFO:oejs.Server:main: jetty-9.4.z-SNAPSHOT; built: 2019-02-20T15:50:58.683Z; git: 3285c4dd4bb00caddcded77f8e44e72c61b9ab72; jvm 1.8.0_211-b12
2019-07-02 16:47:30.693:INFO:oejs.session:main: DefaultSessionIdManager workerName=node0
2019-07-02 16:47:30.693:INFO:oejs.session:main: No SessionScavenger set, using defaults
2019-07-02 16:47:30.694:INFO:oejs.session:main: node0 Scavenging every 600000ms
There was no any AspectJ tracing related info in the output

I found a workaround which lets me run the server without problems and also use different types of aspect pointcuts on all sorts of classes such as internal Jetty classes:
Copy the AspectJ weaver and your aspect library (JAR containing aspects and META-INF/aop.xml) to a subdirectory lib of where you are starting your ords.war. Then append the aspect library to the JVM boot classpath. You need to use a JRE/JDK version like Java 8 which actually still supports the boot classpath. (Actually I just checked, JDK 11 still supports it.) I don't know how to do this with modularised JREs. Then start your WAR like this:
java -Xbootclasspath/a:lib/aspect.jar -javaagent:lib/aspectjweaver.jar -jar ords.war standalone
One more time, with line breaks inserted:
java
-Xbootclasspath/a:lib/aspect.jar
-javaagent:lib/aspectjweaver.jar
-jar ords.war standalone
This approach makes sure that the weaver is attached and its as well as the aspect classes are found before the Oracle JAR classloader does its entry point magic.
Please note that you do not need to modify the WAR file at all here.
Update: As an alternative you could attach the AspectJ weaving agent dynamically instead of via -javaagent, see
my other answer
AspectJ feature description
I quickly tested it, it works. It is kind of tricky, though:
You would have to put your own main class similar to the one in the AspectJ read-me into the WAR as main class. That class would attach the weaver and then start the JAR classloader. Now the weaver is already in place and everything works as expected.
A caveat is that you need to start the JVM with tools.jar, myaspect.jar and aspectjweaver.jar on the classpath,
either on boot classpath if you want to start the application with java -jar my.war
or on the normal classpath You if it is okay to start the application with -cp ...;my.war my.own.MainClass.
Also since Java 9 there is no tools.jar anymore but you need to make your own entry point class dependent on the module jdk.attach and also make sure that you actually run the application with a JDK, not a JRE. Otherwise you cannot use the API for dynamically attaching agents.
All in all I still favour the original solution, it is much easier to implement.

Related

Liquibase resource found in both Maven target and Maven repository

I have Eclipse Maven GWT project and I added flowable-form-engine dependency that uses Liquibase. Liquibase is searching for changelog file org/flowable/form/db/liquibase/flowable-form-db-changelog.xml but finds two!
org.flowable.common.engine.api.FlowableException: Error initialising form data schema
at org.flowable.form.engine.impl.db.FormDbSchemaManager.initSchema(FormDbSchemaManager.java:58)
at org.flowable.form.engine.impl.cmd.SchemaOperationsFormEngineBuild.execute(SchemaOperationsFormEngineBuild.java:29)
at org.flowable.form.engine.impl.cmd.SchemaOperationsFormEngineBuild.execute(SchemaOperationsFormEngineBuild.java:24)
at org.flowable.common.engine.impl.interceptor.DefaultCommandInvoker.execute(DefaultCommandInvoker.java:10)
at org.flowable.common.engine.impl.interceptor.TransactionContextInterceptor.execute(TransactionContextInterceptor.java:53)
at org.flowable.common.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:71)
at org.flowable.common.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:30)
at org.flowable.common.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:56)
at org.flowable.form.engine.impl.FormEngineImpl.<init>(FormEngineImpl.java:45)
at org.flowable.form.engine.FormEngineConfiguration.buildFormEngine(FormEngineConfiguration.java:172)
at org.flowable.form.engine.configurator.FormEngineConfigurator.initFormEngine(FormEngineConfigurator.java:83)
at org.flowable.form.engine.configurator.FormEngineConfigurator.configure(FormEngineConfigurator.java:63)
at org.flowable.common.engine.impl.AbstractEngineConfiguration.configuratorsAfterInit(AbstractEngineConfiguration.java:859)
at org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl.init(ProcessEngineConfigurationImpl.java:985)
at org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl.buildProcessEngine(ProcessEngineConfigurationImpl.java:887)
at sk.dominanz.coarui.server.services.WorkflowServiceAdditional.<clinit>(WorkflowServiceAdditional.java:64)
... 33 more
Caused by: liquibase.exception.ChangeLogParseException: Error Reading Migration File: Found 2 files that match org/flowable/form/db/liquibase/flowable-form-db-changelog.xml
at liquibase.parser.core.xml.XMLChangeLogSAXParser.parseToNode(XMLChangeLogSAXParser.java:118)
at liquibase.parser.core.xml.AbstractChangeLogParser.parse(AbstractChangeLogParser.java:15)
at liquibase.Liquibase.getDatabaseChangeLog(Liquibase.java:217)
at liquibase.Liquibase.update(Liquibase.java:190)
at liquibase.Liquibase.update(Liquibase.java:179)
at liquibase.Liquibase.update(Liquibase.java:175)
at liquibase.Liquibase.update(Liquibase.java:168)
at org.flowable.form.engine.impl.db.FormDbSchemaManager.initSchema(FormDbSchemaManager.java:52)
... 48 more
Caused by: java.io.IOException: Found 2 files that match org/flowable/form/db/liquibase/flowable-form-db-changelog.xml
at liquibase.util.StreamUtil.singleInputStream(StreamUtil.java:206)
at liquibase.parser.core.xml.XMLChangeLogSAXParser.parseToNode(XMLChangeLogSAXParser.java:71)
... 55 more
So I debugged it and it finds one resource from target directory:
jar:file:/C:/work/git/coarui/target/Main-1.0-SNAPSHOT/WEB-INF/lib/flowable-form-engine-6.4.0.jar!/org/flowable/form/db/liquibase/flowable-form-db-changelog.xml
and other resource from maven repository:
jar:file:/C:/Users/Piro/.m2/repository/org/flowable/flowable-form-engine/6.4.0/flowable-form-engine-6.4.0.jar!/org/flowable/form/db/liquibase/flowable-form-db-changelog.xml
Is there a way to ignore one of them, or is my build path or dependency definition wrong?
My build path contains:
src/main/java sources
src/test/java sources
JRE System library
Maven dependencies (in C:/Users/Piro/.m2/repository...)
JUnit4
Looking at source code resources are read classLoader.getResources(path); where class loader is jetty class loader JettyLauncher$WebAppContextWithReload$WebAppClassLoaderExtension.
In my run/debug configuration I have classpath similar to build path plus GWT library gwt-dev-2.8.1.jar - C:\Users\Piro\.m2\repository\com\google\gwt\gwt-dev\2.8.1
In pom.xml dependency is defined as:
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-form-engine-configurator</artifactId>
<version>${flowableVersion}</version>
</dependency>
Maven GWT plugin groupId=net.ltgt.gwt.maven, artifactId=gwt-maven-plugin has configuration parameter classpathScope but I tested <classpathScope>compile+runtime</classpathScope>, <classpathScope>compile</classpathScope> and <classpathScope>runtime</classpathScope> and the same error occurs.
Searching the internet I found similar posts on flowable forum (1, 2) but no solution is provided.
This generally happens when you mix client and server code in the same Maven module, and given how GWT works there's no (easy) around that, besides splitting your code in separate client and server (and possibly shared) Maven modules.
You can have a look at https://github.com/tbroyer/gwt-maven-archetypes for examples (disclaimer: I'm the author, but also a member of GWT's Steering Committee)
it seems that for some reason your .m2 is in the classpath. If it really makes sense to you then you can try to use <scope>provided</scope> in a pom where you declare dependency to flowable-form-engine-configurator. However you may decide to exclude .m2 from classpath which is better I think.

scala typesafe config - How to load conf file from classpath not from top level resources

I am using scala typesafe config (version 1.2.1) in one of my projects to read the application.conf file, my project has dependency on multiple other projects and I create a jar with dependencies to run the dependency projects.
Problem - those projects also use typesafe and has application.conf files in top level directory and my maven jar with dependencies pick up only one application.conf in same classpath and drops rest of them (I tried using maven shade plugin to merge these conf files and I don't want to go that route). I am trying to place these application.conf files in packages, so they don't get overriden in jar with dependencies, but typesafe doesn't seem to recognize the files under a package name in resources directory, it can only find the conf file if placed under top level resources directory.
Is there a better solution to achieve this by using typesafe ? or I am open to using a totally different config library for scala if there is any.
Given a file structure like this:
$tree src/main/resources/
src/main/resources
└── path
└── to
└── file
└── xxx.conf
You can load the config with the following command:
val config = ConfigFactory.load("path/to/file/xxx.conf")

How do I ignore/upgrade a module in JBoss Wildfly 9?

I just downloaded Wildfly 9.0.0.CR2 with Java 7 on Mac 10.9.5. I notice by default, Wildfly 9 includes a bouncycastle module (modules/system/layers/base/org/bouncycastle/main/bcprov-jdk15on-1.52.jar) . I would like to install another bouncycastle module in Wildfly (bcprov-jdk16-1.46.jar). Is there a way I can disable the one that JBoss has included? When I tried to delete the module Jboss included (the modules/system/layers/base/org/bouncycastle/ folder), I get the error upon JBoss startup
08:36:19,086 ERROR [org.jboss.as.server] (Controller Boot Thread) WFLYSRV0055: Caught exception during boot: org.jboss.as.controller.persistence.ConfigurationPersistenceException: WFLYCTL0085: Failed to parse configuration
at org.jboss.as.controller.persistence.XmlConfigurationPersister.load(XmlConfigurationPersister.java:131)
at org.jboss.as.server.ServerService.boot(ServerService.java:350)
at org.jboss.as.controller.AbstractControllerService$1.run(AbstractControllerService.java:271)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.xml.stream.XMLStreamException: WFLYCTL0083: Failed to load module org.jboss.as.weld
at org.jboss.as.controller.parsing.ExtensionXml.parseExtensions(ExtensionXml.java:155)
at org.jboss.as.server.parsing.StandaloneXml.readServerElement_1_4(StandaloneXml.java:433)
at org.jboss.as.server.parsing.StandaloneXml.readElement(StandaloneXml.java:144)
at org.jboss.as.server.parsing.StandaloneXml.readElement(StandaloneXml.java:106)
at org.jboss.staxmapper.XMLMapperImpl.processNested(XMLMapperImpl.java:110)
at org.jboss.staxmapper.XMLMapperImpl.parseDocument(XMLMapperImpl.java:69)
at org.jboss.as.controller.persistence.XmlConfigurationPersister.load(XmlConfigurationPersister.java:123)
... 3 more
You might have a look at this discussion, it is almost the same thing you want to do (opposite direction w.r.t. versions):
BouncyCastle 1.51 loading in war on Wildfly 8.0
The long and the short of it is, you can create a custom module (or, I think, another slot for the existing module?) and reference that one in your jboss-deployment-structure.xml instead of the default module wildfly is bringing with it.
If you don't want/need BC as a module, you could also just include it in the lib folder of your EAR/WAR and it will be loadable from there.
Our deployment structure looks essentially like this:
my.ear
+ lib/ <-- dependencies for multi-submodule deployment
+ META-INF/ <-- application.xml defines submodule(s) e.g. web.war,
<-- also jboss-deployment-structure.xml to include/export wildfly core modules for your EAR
+ web.war <-- our core deployment
And we include e.g. a different version of hibernate than in wildfly. I expect you can include a different BC version in your ear as well.
See also:
https://docs.jboss.org/author/display/WFLY8/Class+Loading+in+WildFly
Custom module tutorial:
http://middlewaremagic.com/jboss/?p=1933
Similar issue with resolution: https://developer.jboss.org/thread/175395
WildFly uses modular classloading and as such not everything is on classpath of every module.
Deployment itself is just another module that gets extra dependencies based on what deployment descriptors tell server should be added.
When it comes to bouncycastle, there are modules that themselves require it, but that doesn't mean they will expose this dependency to your deployment.
There was a bug in 8.0 that caused that BC was exposed to user deployment in case when user deployment was using web services. This was fixed since than.
Given that you use WildFly 9 that shouldn't a problem anymore.
As other suggested, you can create new module with different name or at least different slot name, which you can than include via your jboss-deployment-structure.xml
Just btw, bcprov-jdk16-1.46 is much older than what is provided in WildFly.

Simple Hello World demonstrating OSGi with Akka Actors?

I want to create a very simple (Hello Simple World) POC that demonstrates the ability to integrate OSGi (Felix) with Scala and Actors (Akka). Here is what I have so far:
$ tree
.
├── bin
│   └── felix.jar
├── bundle
│   └── akka-osgi_2.10-2.2.1.jar
├── conf
    └── config.properties
$ cat conf/config.properties
org.osgi.framework.storage.clean: onFirstInit
org.osgi.framework.system.packages.extra: javafx
org.osgi.framework.bootdelegation: sun.misc
felix.auto.deploy.action=install,start
felix.log.level=1
org.osgi.service.http.port=8080
obr.repository.url=http://felix.apache.org/obr/releases.xml
$ java -jar bin/felix.jar
ERROR: Bundle com.typesafe.akka.osgi [1] Error starting file:/home/axiopisty/projects/test/bundle/akka-osgi_2.10-2.2.1.jar (org.osgi.framework.BundleException: Unresolved constraint in bundle com.typesafe.akka.osgi [1]: Unable to resolve 1.0: missing requirement [1.0] osgi.wiring.package; (&(osgi.wiring.package=com.typesafe.config)(version>=0.4.1)(!(version>=1.1.0))))
org.osgi.framework.BundleException: Unresolved constraint in bundle com.typesafe.akka.osgi [1]: Unable to resolve 1.0: missing requirement [1.0] osgi.wiring.package; (&(osgi.wiring.package=com.typesafe.config)(version>=0.4.1)(!(version>=1.1.0)))
at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:3974)
at org.apache.felix.framework.Felix.startBundle(Felix.java:2037)
at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1291)
at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:304)
at java.lang.Thread.run(Thread.java:744)
I understand from this error message that there is no bundle that exports osgi.wiring.package. But I don't know which bundle I would need to include that exports that package. Would it come from Akka, from Felix, or from somewhere else?
As can be seen in the provided config.properties I tried to follow the instructions about how to Configure the OSGi Framework from the akka documentation, but I don't know if I'm doing what they said needs to be done in the right way.
The akka documentation says:
To use Akka in an OSGi environment, the
org.osgi.framework.bootdelegation property must be set to always
delegate the sun.misc package to the boot classloader instead of
resolving it through the normal OSGi class space.
How do you do this using Felix as the OSGi container, and using the default felix launcher?
A simple hello world example using OSGi (Felix is not required, but preferred) and Akka Actors is ideally what I'm looking for. If you know of anything on github (or elsewhere) that demonstrates this, I would accept that as an answer too.
There is a sample OSGi application in the Akka source tree. Hopefully you can use it as a staring point. It uses Karaf.
https://github.com/akka/akka/tree/v2.2.3/akka-samples/akka-sample-osgi-dining-hakkers
Make sure to check out the code at a stable tag, like v2.2.3 so the build tools use published stable artifacts of Akka.
missing requirement [1.0] osgi.wiring.package; (&(osgi.wiring.package=com.typesafe.config)
From this part of your error message it seems that your bundle cannot find another bundle that provides com.typesafe.config which is a dependency of akka.
You can circumvent this with the Conditional-Package Header/Instruction of the bnd tool when you create your bundle.
I have started to put an OSGi container based on Karaf together and have shared it on github. For now it simply registers an ActorSystem as a service and has a demo bundle with an Actor in it using that system. It is configured to log into the normal karaf.log.
The code example can be found on github.
Best regards
Andreas

NoClassDefFoundError in Eclipse when adding project in build path

I am receiving an NoClassDefFoundError in Eclipse when I try to run my project.
My Project looks like this:
JavaProject: BulkAdmin
- src
- com.mycompany.bulkadmin.SDK.util
- Login.java
Dynamic Web Project: JSPTesting
- src
- com.mycompany.bulkadmin.jspController
- Controller.java
- WebContent
- index.html
- execute.jsp
This is the control flow:
index.html loads
index.html has a form that redirects to execute.jsp
execute.jsp takes the info returned in the form and makes a static call to Login.java
execute.jsp prints the results of the call
Controller.java uses Login.java. I was receiving compilation errors. To resolve them I did this:
Right click on JSPTesting -> properties
Choose java build path on the left bar
Choose projects tab
Click add
Choose BulkAdmin (Project)
I am not sure why but now when I am getting a NoClassDefFoundError. I have done some googling. I think that this means that I have messed up my classpath somehow but I am not sure how to resolve this.
java.lang.NoClassDefFoundError: com/myCompany/bulkadmin/SDK/util/Login
at com.myCompany.bulkadmin.jspController.Controller.process(Controller.java:44)
at org.apache.jsp.execute_jsp._jspService(execute_jsp.java:63)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:331)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:321)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:257)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:873)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
at java.lang.Thread.run(Thread.java:595)
Other information:
I am using tomcat (in Eclipse) as my server
The exception shows up in the browser and the eclipse console
execute.jsp is a JSP
It seems like there are many similar questions to this on SO. I have read about 15 of them and tried various things however I think that my question has a different solution. I can provide more information.
Rightclick your dynamic web project, go to Properties > Deployment Assembly and add the dependent projects there. This way they will end up as JAR in /WEB-INF/lib, exactly there where you want it to be.
In Eclipse versions older than 3.5 you need to go to Properties > Java EE Module Dependencies.
See also:
ClassNotFoundException when using User Libraries in Eclipse build path
Difference between Deployment Assembly and J2EE Module Dependencies in Eclipse
The NoClassDefFoundError indicates that a class that was available during compilation is no longer available at runtime. Your problem is that the com/myCompany/bulkadmin/cSDK/util/Login class is available in the compilation classpath (in Eclipse via the Project reference you added to the build path) but not in the runtime classpath (Tomcat, which has no idea how to find this class).
You need to add the BulkAdmin project to the web-app class path when deployed on Tomcat as well.
One way to do this would be to export the BulkAdmin project as a JAR and put it into the WEB-INF/lib directory of your JSPTesting project.