So far, I have created a web application using JAX-RS (Jersey) and Maven as build and dependency managment, but for this question, I'm not sure it matters. I'm using h2k as DI framework. It works fine and I can package the application as a WAR which can be deployed to a tomcat server (both locally and remote).
The application is configured using jersey's ResourceConfig, where I also configure my AbstractBinder (for h2k) to bind my #Inject to concrete instances. So far so good. Now I want to use Jetty (or grizzly) as an embedded server for local development (by mvn jetty:run), and automate the build of the war for remote deployment. I want to use different classes (injected by hk2) depending on the environment (eg. fake email sender, on test server), and this is where I'm stuck. How do I specify which environment I'm running in and how do I specify which classes to use for each environment?
Maybe my problem is in my understanding of how all this works (Examples of actual build setups would be warmly welcomed). Normally I just use AbstractFactory, which I inject into my main method. My guess on how this should be done:
I should create a properties / xml file for each environment, where I specify which implementations and properties should be used.
When running or building, I should specify which environment I'm running in (for instance mvn build -ENVIRONMENT)
Related
I'm not sure if this is the best place to post such a question, but here it is. I'm a test automation engineer that works primarily with backend, spring boot command line apps. My tests, at a high level, are designed to ensure that any type of data that is thrown at the app will be handled correctly. We are a Java shop.
As with any "good" testing practice, I am treating the app like a blackbox, in that I do not pull in the model objects to run my tests. I simply supply the app with data, execute a command line type script (run.sh) that takes my data and processes it. My tests are comprised mostly of JDBC (to interact with the database) and a slew of ArrayList utilities that I have put together to sort out result sets and get specific db information.
Thus far, I have been deploying my tests as a JAR. I bundle everything up and deploy it to the environment with a script that will execute the tests. The tests do not run when the app is run. Though they do live inside of the project, they are a separate entity with separate launcher classes. However, I am finding that managing dependencies in a JAR is a real headache. Is there a better way to deploy automation / integration tests for command line apps?
I'm pulling in maven shade plugin to bundle all of my dependencies into a "God JAR", but that isn't helping me to resolve the issues that occur when I attempt to execute the JAR. I get multiple bean instantiation errors, relating to the app itself, and not my tests. For this reason, I pull in the app model, and the app itself as dependencies. When I ran the tests in my initial testing, they worked just fine. Deployed to environment and they continued to work correctly. Fast forward a couple of months, a few changes made to the app, and now it's a dependency nightmare when I build the new JAR.
TLDR: I'm having trouble managing dependencies in a maven project, integration tests JAR. Is there a better way to deploy automation / integration tests for command line apps where dependency management is easier?
(Note: I'm relatively new to this world, so pardon me if the question seems a bit vague).
I think the error happens when you use the shade plugin to re-package the spring boot jar. The way spring boot works is to add dependencies into the jar as jars itself and configure its own class loader (in the meta config) that is capable of reading classes from jar files inside the jar file. The standard java class loader does not do this - thats probably why the shade plugin misses out some jars (probably the ones embedded in the spring boot uber jar).
what I would try is to create a test-version of the spring boot app that contains the test-classes in the compile scope and a dependency to the original spring boot jar (you don't need the uber jar - therefore you may have to add a classifier to the original (app) spring boot plugin config to have that jar still available as it is replaced by default) and use the spring boot plugin to package the test version of it (using the dependency and its classifier above you used for the original app).
I'm currently developing a plugin system in which I embed apache felix in my application. The plugins itself are the OSGi bundles. So far deploying the bundles works just fine but I have trouble interacting with my bundles/plugins. I tried two approaches:
Register the a service "Plugin" in my Plugin and use the service listener in my "host" application to interact with the plugins.
The service listener is not invoked and I can't cast the returned Plugin object because the Plugin.class of my Host application is a different one compared to the Plugin.class thats inside the bundle.
Register the "PluginManager" in the host application and load this manager in the bundle.
In this case I'm again unable to cast the service class because of this class "duplication" issue.
I understand why the classes are "duplicated" but I'm not sure what to do about it.
My current setup:
plugin-api maven module: Provides Plugin interface
app maven module: Contains the app which embeds Apache Felix
dummy plugin has only a dependency on plugin-api
Is there a problem with the way my setup is structured? How can I access host services without creating a class mess? Should I create another module which is used to compile my plugin but it is excluded from the bundle and later provided on the host via FRAMEWORK_SYSTEMPACKAGES_EXTRA?
You should define your Plugin API (and all the non-VM based types that it uses) on the application side. If I would do this, I would make an API bundle (yes bundle) that exports these packages.
Make sure that all plugins not export the API or at least allow it to be imported.
In your application, before you start your Felix embedded framework, you get all the manifests of all JARs on the classpath with getResources("META-INF/MANIFEST.MF")and check for Export-Package. Then concatenate all these exported packages and set the OSGi Framework property org.osgi.framework.system.packages.extra to the joined string.
This will export any package on your classpath, so also your API bundle. Since the framework now exports these packages, your plugins will use the standard classpath as provider. Therefore, the API will have only one source and you will not get into class hell.
Since I learn from some maven tutorials we can import Jetty as a maven plugin like this.
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.10</version>
<configuration>
<scanIntervalSeconds>5</scanIntervalSeconds>
</configuration>
</plugin>
And can run the plugin like this.
$ mvn jetty:run
Also we can change the port and context path and lots of stuff in this plugin.
As I understood that we can use Jetty as a server like tomcat, and we can deploy an application through it.
But the thing I don't understand is what is the actual enterprise use of Jetty in maven..
From the official documentation:
The Jetty Maven plugin is useful for rapid development and testing. You can add it to any webapp project that is structured according to the Maven defaults. The plugin can then periodically scan your project for changes and automatically redeploy the webapp if any are found. This makes the development cycle more productive by eliminating the build and deploy steps: you use your IDE to make changes to the project, and the running web container automatically picks them up, allowing you to test them straight away.
However (and maybe this addresses what you call "enterprise use"):
While the Jetty Maven Plugin can be very useful for development we do not recommend its use in a production capacity. In order for the plugin to work it needs to leverage many internal Maven apis and Maven itself it not a production deployment tool. We recommend either the traditional distribution deployment approach or using embedded Jetty.
The main usage is for testing, Jetty can also be started programmatically (see this example Java code) which means you can start server directly from your code and interact with your REST API for instance.
You can also use it for easier deployment of small applications, just package everything into the JAR which runs server from main method when executed via java -jar your-app.jar. You don't need any dependencies installed except Java then.
As a side note, I currently work in Clojure (JVM language based on Lisp) and many people deploys their application as JAR which internally runs embedded Jetty because this way it's also starts REPL which you can connect to remotely and debug your application when it's running.
I don't know exactly what you mean by enterprise use, but let's say you're developing a web application and it's a Maven project.
Each time you want to test whether the web application works correctly, you need to deploy the web archive (WAR) on a web server, e.g. Jetty or Tomcat. Usually this involves a couple of manual steps like:
Start the web server
Deploy the WAR on it
Where the Maven plugin comes in handy is that it allows you to just execute
mvn jetty:run-war
and it does all these steps automatically for you in a single command, saving you lots of time. The plugin is even able to redeploy the application once it notices changes have been made.
For a java project I want to spin up a server application during integration test (maven-failsafe-plugin, can be switched).
Problem
The server application should be fetched via maven
My project and the server depend on a shared library
The version of my copy of the shared lib may be different then the one of the server application
(During test there is even a third application involved, but the same requirements apply)
Current solution
Create a classloader manually, built classpath manually, start server application in custom classpath
manual dependency resolution sucks. Has to be redone on dependency changes.
Put everything onto the classpath, remove stuff that breaks.
Also manual...
Wish
Specify a "dependency profile" in pom.xml for each component
During test call something like: Maven.getClassLoaderForProfile("server"), receiving a classloader with all dependencies (including transitive ones)
Load application in this classloader
Is there any workable alternative to jetty-maven-plugin? This particular plugin is not supported properly. I even failed to find its source code repository.
What I need is an embedded container for integration testing.
There is a very similar Tomcat Maven Plugin. Works exactly the same, except... it uses Tomcat. You might also try Maven Cargo plugin that uniforms deploy process to several different containers/servers.
There's an embedded-glassfish plugin that can be used for this.
I often use an embedded jetty server that is started in the #beforeClass part of an junit test. That embedded jetty along with openejb provides most things you need without having to deploy your application anywhere