Our team is writing a server-client application where the frontend is an Angular.js single page application which uses a Spring MVC java backend. The backend serves the application files and the REST endpoints used by the browser end. We are using Maven as the main build system for the application.
We like to take advantage of require.js and r.js to minify the app at the end, and we are also using client side dependency management. Currently we are using bower to download Javascript libraries required but it doesn't feel right to me to download client dependencies to src/main/webapp since this is a source folder. However in order to avoid rebuilding the whole frontend module each time something changes in the client files, this seems the only sensible way to us. This way we can start a web server and it will automatically pick up changes without restart, but as i said this doesn't fit Maven's folder layout.
I'm experimenting with Webjars which seems a better choice in our Maven oriented build and dependency management. Because in Servlet 3.0 containers webjar resources are provided automatically on the server container path it's very easy to use and manage them. It's also possible to create a require.js config to refer to libraries contained in webjars since they are on the webserver path the same way if they were static files, the serving is being done transparently in the client applications point of view.
My only problem is that i don't know how could we achieve r.js minification with this layout, since the source files are in jar files r.js cannot access them. Also the require.js config refers to the runtime server paths which are simply not there in build time.
I see that webjars now have some integration with Require.js + Play Framework but we are not using Play just simple Spring MVC in our case. I really hope there is a way to handle this case because i like the Webjar way of client dependency handling.
You need an asset compiler / pipeline in your build process. There are probably many options but the one I know of is wro4j: http://alexo.github.io/wro4j/
Related
I am a Spring Boot newbie. I'd like to initialise a project which consists of:
A console application that acts on command line arguments so the JAR files could be later used in scheduled tasks.
Consumes a RESTful service
Logging
Which package dependencies should I choose in Spring Initializer? Apart from the necessary packages, are there any libraries that are optional but make development easier?
Depends on how you want to consume the restful service, but you may not need any extra starters, the core spring-boot-starter that you get when you just hit "Generate Project" and is usually implied with all the common starters like -web, -security, .. has logging and dependency injection and is all you need to create a jar that can easily be started with java -jar
However, it does not come with RestTemplate which is a common way to build rest clients in spring. For that you'll need to manually add a dependency on org.springframework:spring-web like you can see examples for in https://spring.io/guides/gs/consuming-rest/
But you can as well use other rest client libraries if you like them better.
There is also Feign that can be used as rest client and it's available from the initializer, examples at https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html - have not tried it and I'm not sure how much extra cloud dependencies will be added when you add the starter.
I also like having Lombok in all projects but that's preference. The obvious sounding choice of DevTools doesn't give you much benefit in a console application but is great for live reloading of web servers.
[...] so the JAR files could be later used in scheduled tasks.
sounds like you're trying to create a library / module of a larger application. You don't need an application that works standalone for that though so maybe https://spring.io/guides/gs/multi-module/ is good to read for you. Difference for libraries is that you don't need the spring boot plugin for maven/gradle which can package a standalone jar, just the dependency management.
Typically on a Java project using Maven, you place client-side source files in src/main/webapp. This directory includes your html, css, scripts, images, etc.
However, many grunt projects tend to place these files on the root. It's as if Grunt was designed with the idea that your project is the client-side application, not part of a large server-side project, such as using Java with Spring.
Given a Java project using Maven, where would be the best place to put your web-related source files?
Do you place them in src/main/webapp?
Do you make another directory altogether, such as src/web, and then on a build, copy everything to src/main/webapp?
My goal is to make the client-side build tool as transparent as possible. I guess the ideal case is to simply work from src/main/webapp as I have been doing all along - this is pretty unobtrusive to the way my project is currently setup.
However, if I work from src/main/webapp, I know that I will need to distinguish between src and build directories somehow anyway. I'm sure my html files can stay where they are, but there's definitely going to be a conflict of interest here with javascript and css files, and maybe images too.
Does it make sense to literally have a 100% separate source folder from src/main/webapp? Is there a way to do continuous building/copying/syncing of the application as you modify files, from src/web to src/main/webapp? Will this be inconvenient and cause frustrations and problems? Is it slow?
I would like any advice on the subject. Thank you.
Option 1: Put UI resources in src/main/webapp:
This is a quick-n-dirty solution popular on Github. It helps to keep example projects small and concise. In this case, usually people put the package.json, bower.json, Gruntfile.js and .bowerrc in the maven project's root directory, where the .bowerrc says to install components into src/main/webapp/bower_components.
If you have a task that minifies/transforms resources, the transformed resources can go to a new directory like src/main/webapp/dist. Then use something like grunt-usemin to make your app use the resources in the dist directory.
If your application will use a security framework (like, say, Spring Security), you might want all your resources in src/main/webapp so that the security framework can regulate access to those resources. However you can still achieve this using Option 2 by having a grunt task that copies the necessary resources into src/main/webapp.
Pros
Common approach on GitHub. Keeps everything in one project.
Cons
The version of files getting served by your server is a copy of those in src/main/webapp, so changing a file in src/main/webapp isn't immediately reflected in your deployed app. To get hot reloading, you need to use something like grunt-contrib-* stuff.
Frontend and backend code is all mixed together. Harder for two different teams to work on the code base.
Option 2: Put UI resources in a separate project:
You can achieve better project organization by keeping the UI and backend in completely separate projects. In this case the UI and the maven project would likely be sibling directories.
Then when deploying to a server, you either:
deploy both projects separately (call them myproject-ui and myproject-services). The javascript in myproject-ui makes RESTful service calls to myproject-services/**.
Use a grunt task to copy necessary resources to src/main/webapp, then deploy your (one) project.
Pros
The backend and the frontend are separated as much as possible
The frontend maintains the workflow and directory structure found in most client-side example apps, as you mentioned
"Deploying" the UI is a simple matter of creating a symlink from your server's deployment directory to you UI source code. Changing any UI code is automatically reflected in the deployed app.
You can have several different UIs deployed simultaneously (maybe you have myproject-admin-ui and myproject-user-ui). You could hit either one simply by visiting
http://localhost:8080/myproject-admin-ui
http://localhost:8080/myproject-user-ui
I have a maven project which generate zip generated from ant scripts. Then this zip is deployed to specific application server again using ant script. this is very complex for maintenance. Now we move to use maven for building zip, so what is standard way to doing with respect to developer and client
How to handle application server specific deployment(e.g for weblogic and jboss) Do I need to create 2 zip for each server?
How to handle global configuration parameter like database, product specific settings. Where to put them, and how it use by developer and client?
The installation of application sever is need to integrate with build cycle or what is best practice for it?
I'll try to answer based on my experience:
I use maven profiles for this. Especially since there are beans (classes) that are specific to only one app server at a time. See http://maven.apache.org/guides/introduction/introduction-to-profiles.html
maven supports placeholders. One build for every single environment: dev/qa/prod,etc. All you need is the properties file. (this is similar to properties in ant)
You do not need (usually, unless you have integration tests that are tight to the app server - and if you do, it seems wrong) an app server for the build itself.
I have a Struts web app deployed to an EAR that has some pretty extensive JavaScript. I now need to create a new web app that will be deployed to a new EAR but will probably need to share most if not all of the JavaScript and some images from the first application. What's the best way to avoid code duplication so I don't have to put a copy of each JavaScript file in each EAR in my development environment?
You could maintain the Javascript in a separate .jar library and serve it as a resource, not as a static file. That way the JS content would be a regular dependency in your project setup. Unfortunately there isn't a straightforward universal way to do this because you need at the very least a servlet that will send the file from the .jar. (Depending on your web framework you might already have this available.)
This also has some performance implications, but for a line of business application you probably don't need to optimize the load time of your internal Javascripts all that heavily.
Another alternative would be doing this at the source control level, using something like Git submodules.
I am a novice with JavaEE but have some experience with ASP.NET MVC. With ASP.NET MVC, I know we can make a plugin architecture with ASP.NET MVC web app so you can make a dll with MVC structure and put it into the existing ASP.NET MVC web app to make it work without compiling the web app. http://www.wynia.org/wordpress/2008/12/05/aspnet-mvc-plugins/
I wonder if this kind of architecture is possible with Spring MVC. For example, when I make a jar (or war) file with MVC structure and put it into existing Spring MVC web app, it should work without recompiling the web app. If this is possible, how can I achieve that? Any reference would be appreciated.
It is possible without recompiling, but probably not without restarting. You could create a .jar which you drop into the WEB-INF/lib directory. By using classpath scanning you should be able to deploy your new controllers on start-up. You can skip the view entirely and directly output data to the ServletResponse. Rendering a view from a jar may or may not be possible, I don't know.
Sounds like you want to search for "hotdeploy".
What you are asking for is not a feature of Spring, but rather a feature of JVM and the application server. The application server is able to see that indeed your classes have changed and using some clever ClassLoader trickery it can load new versions to the runinng JVM as they become available. Java was not actually designed to work like this so there are some issues (ClassLoader, memory leak, hotdeploy are good keywords for finding more about the potential problems and possible solutions). I would not recommend this for production use but it can be handy during development.
Since this is a feature of the application servers, the actual details depend on the particular application server and are explained in it's documentation.
If you simply want some plugin-magic, not actual hotdeploy, there are other things you could do. A custom ClassLoader can load classes from whatever source (file, network, database..) you want and then you can instantiate and use these with reflection. (This is what happens when you deploy the war to Tomcat/JBoss or whatever). Accessing and dynamically reloading non-class resources inside jar/war files is way easier.