Working on a DropWizard project for the first time which uses the docker-config.yml file to run the server using the jar file.
The command I run on the terminal to run the server is something like this:
java -jar target/foo-0.0.1.jar server conf/docker-conf.yml
Do I have to run mvn package every single time I make a change? (for eg: even a small change like adding a System.out.println() statement to debug something)
mvn package is used to create a JAR - a deployable artifact of the application. So if you really want to create the JAR every time, yes you need to package everything.
However, usually if you’re talking about small changes like adding System.out.println I assume that you have some “work-in-progress”. In this case you can configure your IDE to run the class with main method (the Application class in in terms of dropwizard framework). It won’t create a fat jar but for debugging you also don’t really need it.
This is what I (and I believe many of our colleagues) do when working with applications powered by dropwizard, spring-boot (which is similar in this aspect), etc.
Related
I would really like to do something like ./gradlew build -cp /$HOME/my/custom/testerLibrary.jar but I cannot find a straight answer anywhere. I have a special case where I need to add a jar to the class path because the class that I use for manual testing requires it, but nothing else in my project needs it and I don't want to include it in my build.gradle.
Should I create 2 projects where project A is run manually to debug project B?
You can create two JARs from the same source code:
the production application
the manual-testing application
The manual-testing application (2 in the list above) could be created using a Gradle task that appends the required JAR to the classpath:
task createManualTestingApp(type: JavaExec) {
classpath += "/$HOME/my/custom/testerLibrary.jar"
// ...other configuration...
}
If you want the task that creates the production JAR and the manual-testing JAR to be identical, except that the manual testing JAR contains the augmented classpath, this can be done by creating two tasks that extend the same type: How to extend the behavior of a Gradle task for a new task type?
Opinion: From a testing perspective, it is not ideal to have a JAR that is included in the manual-testing application but not in the production application. This results in a test application that is different than the production application. For example, what if that JAR includes something or changes the behavior of the application that causes the manual tests to work but the production application fails because it is missing that JAR? Depending on the nature of the JAR, this may be benign, but it is important to consider when deciding that the test and production applications will be different.
I'm trying to Play 2 application on Windows Server Server 2012 using the "stage" task, with the goal of wrapping this up in a service so the application will automatically run when the server gets restarted. However, when running the app I get the following message:
The input line is too long.
The syntax of the command is incorrect.
This is because Windows has a limit of around 8000 characters for command line instructions but it seems like the Play stage command is exceeding this by passing the classpath as an argument.
Copying the "stage" folder to c:\ might fix the issue (as it'll reduce the size of the classpath) but I was hoping there would be a more elegant solution.
Has anyone found a way around this? Alternatively, do people have any suggestions for running a Play application on Windows so that it will automatically run when the server is restarted.
Thanks.
I also had the same issue and I wasn't satisfied with the solutions that you provided.
I have found a simpler solution.
Add the following line to the build.sbt file
lazy val root = (project in file(".")).enablePlugins(PlayScala, LauncherJarPlugin)
Now if you generate your production application with:
sbt dist
or run a production mode with
sbt start
The LauncherJarPlugin plugin will take care for generating proper bash/batch run scrips.
To get to know more about LauncherJarPlugin please read the documentation:
Sbt documentation about long classpath
How to enable plugin in build sbt
UPDATE: sbt native packager now comes with a number of built in solutions to this, see NieMaszNic's answer below.
This is a known issue, being tracked in the SBT native packager (which generates the start script) here:
https://github.com/sbt/sbt-native-packager/issues/72
My recommendation to work around this issue would be to write your own start batch script that uses a wildcard classpath matcher. You can put this script in the dist directory in your Play project, and it will end up being packaged up with your application. That script might look like this:
java %1 -cp "./lib/*;" play.core.server.NettyServer .
Note that if you use a wildcard classpath matcher, you can no longer rely on classpath ordering to be the same as in dev mode. You shouldn't rely on classpath ordering anyway, but people inevitably do.
Taking James's suggestions into account, the following solution works for a Play 2 application.
CD into the app and run play clean stage
Copy [your_app]/target/universal/stage/bin/[YOUR_APP].bat to [your_app]/dist (you may need to create the "dist" directory). I renamed the file as [your_app]_windows.bat to make it clear but the name doesn't really matter. Files in the "dist" directory get copied across with your app the next time you run the stage task (thanks James).
Open your new bat file in a text editor.
Files put in the "dist" directory are put in the "universal" directory (not "bin") so you'll need to change the home variable, i.e. remove the two full stops at the end so it doesn't navigate to the parent directory (on line 11 at present),
e.g.
if "%WEB_PORTAL_HOME%"=="" set "WEB_PORTAL_HOME=%~dp0\\.."
becomes:
if "%WEB_PORTAL_HOME%"=="" set "WEB_PORTAL_HOME=%~dp0"
You then need to change the class path, as per James's instructions, to use a wildcard rather than explicitly listing all the JAR files (at the moment this is on line 91)
e.g.
set "APP_CLASSPATH=%APP_LIB_DIR%\web-portal.web-portal-1.0-SNAPSHOT.jar;%APP_LIB_DIR%\commons-c.....
becomes:
set "APP_CLASSPATH=%APP_LIB_DIR%\web-portal.web-portal-1.0-SNAPSHOT.jar;%APP_LIB_DIR%\\*"
You can then run your new script (which is copied into the [your_app]/target/stage/universal directory).
Important: I'd recommend re-creating this file every time you upgrade
Play just in case the build script changes in future releases.
Change the longest line in your bat file with:
set "APP_CLASSPATH=%APP_LIB_DIR%\..\conf\;%APP_LIB_DIR%\*"
just before
set "APP_MAIN_CLASS=play.core.server.ProdServerStart"
Enable LauncherJarPlugin first
lazy val root = (project in file(".")).enablePlugins(PlayJava, PlayEbean, LauncherJarPlugin)
Then if you want just to start play with production mode you can use activator :
activator clean compile stage testProd
or fast version :
activator testProd
This will run play in production mode, i'm not sure if you have to addstage to command because i'm pretty sure that its already building with testProd, but its better to make sure you built the stage version.
I have multiple Java projects in Eclipse, which I would like to sometimes run with some arguments (same args for every project). Therefore I would like to create a Run Configuration which I would run on chosen project. Creating a RC for every project is a little too much hassle for me. Ideal solution for me is that I could click on a project or main class, select my run configuration and I'd run this project with specified arguments. Or maybe somebody could come up with some clever and usable alternative?
There are a few quirks, but it is doable.
Main
Project must be specified explicitly, but it is not that relevant for your use case.
Use ${java_type_name} as Main class name.
JRE
Select an appropriate JRE
Classpath
Make sure the JRE is selected in Bootstrap Entries
User entries must contain a variable string ${project_classpath}
I have a little java project which is build in gradle. I imported the project to eclipse. The gradle task run starts the server and run the application in localhost(using Tomcat). Problem is, how to refresh my .java data instead of re-run the application always again. This takes time. I can change my .jsp files in build directory and after page refreshing data changes. But problem is .java files. In gradle there are task install which compile the whole project(shows errors if have), but the page content doesnt change, so i have to run project again to see the changes.
I have .class-es in 2 places. In build directory and exploded/WEB-INF. IMO, if application runs, it is using build directory files, but i dont know what files are in WEB-INF directory...
Redeployment has always been a great time consumer. There are a couple of tools(some comercial) that will help you, like JRebel. If you want to use Netbeans, there is a deploy on save option too. I don't know any other options, I'm sure there are a few more, but anyway, this should be a good start.
The easiest way is to start your application with debugger flags, then every time you update and compile your source code, the JVM will pick-up a new version automatically, without redeployment, it is called "hot-swapping".
You will need to add something similar to your run task:
-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005
Then attach Eclipse debugger to localhost:5005 and you will be good to go. It will not work if you are changing method signatures, add new class attributes or constants. Apply your changes within existing methods, then once everything works as expected, refactor and restart.
More information on debugging with Eclipse: Debugging With Eclipse Platform
Some weeks ago at work I took over a Java-based back-end web application written using Eclipse. The nature of the application is that it cannot be adequately tested locally, and instead changes need to be tested on our testing network (which involves pushing the changes to an AWS Micro server that we connect to via SSH).
Until now, I pushed changes in the same way as my predecessor: compile the program using Eclipse's Export to Runnable JAR File option, then scp the jar to the remote server and run it. However, this process has a huge problem. While compilation takes only seconds, the jar is well over 30MB, and pushing the entire thing from the office to the remote server over our fairly ordinary internet connection takes well over 10 minutes. If I'm having a particularly bad day and, say, introduce several minor bugs to the code and then discover them one by one, I can easily end up losing an hour or more in total twiddling my thumbs while pushing the whole jar over and over for a series of one-line changes.
Clearly, a saner solution than scping the entire jar for every change would be to simply remotely pull only the changed .java files from source control, and then compile the new version entirely remotely. However, I'm quite new to Java (and indeed programming generally) and all my Java work has been on existing Eclipse projects that I've taken over partway through development. As such, I know very little about compiling Java, and I have found the tutorials about this online are mostly either opaque or completely fail to address the question of how to compile code that uses external libraries.
I will relate here what information about the project's dependencies I can find from Eclipse, and my questions are these: what do I need to copy to the remote server, and where do I need to put it, to be able to compile remotely? What tools, if any, do I need to install on the remote server to be able to compile there? And once I've got everything set up, what do I actually type at the command line to get it to compile?
Anyway, here's what I know about the dependencies and directory structure (I've anonymised our application name by calling it “bunnies”):
The application source code is located in bunnies/src
We compile to bunnies/bin/main.jar
bunnies/dependencies contains three jars of external libraries that we use.
Right-clicking on the project in Eclipse, going to the Java Build Path section, and selecting the Libraries tab, I see
the three libraries above
(appearing in the form, e.g. “json-simple-1.1.1.jar - /home/mark/workspace/bunnies/dependencies”)
a fourth jar file in another location
(“M2_REPO/com/google/guava/guava/r09/guava-r09.jar - /home/mark/.m2/repository/com/google/guava/guava/r09/guava-r09.jar”)
JRE System Library [java-6-openjdk-i386]
But there's more! We also use two libraries, mahout-core and mahout-integration, that are included as separate projects in the same workspace rather than as jar files in the dependencies folder. They appear by name on the Projects tab of the Java Build Path section of the bunnies project, and are located at /home/mark/workspace/mahout-core and /home/mark/workspace/mahout-integration respectively.
Since I am not a Java whiz, perhaps there are also some other hidden dependencies I'm missing, that don't appear in any of the places I've looked so far?
If anyone can walk me through the steps of compiling this huge mess from the command line, without needing to use the Export option in Eclipse, so that I can ultimately compile it all remotely, I would be highly appreciative.
Look into Apache Ant. It's a build-suite for Java, sort of like an XML based Makefile system.
I have a Java system running on a remote server. I have a directory structure separated into /src and /build. I then just scp the .java files from my local machine to the /src folder and build using ant.