"one version rule" in Java dependency management--is this a good idea - java

For security reason, we update third-party dependencies frequently.
We use maven as our dependency management tool , but it's still a hard work since we have 100+ projects to update.
1、How can we do this fast and sound?
Sometimes we have to change our code to use the new dependency. Sometimes we don't have enough time to test and cause exceptions in product environment, like NoSuchMethodError.
2、Is One version rule a good idea in java? Have someone done this before?
for example, our Project A depends spring-webmvc 5.3.9 and Project B depends on spring-webmvc 5.2.0. We want both A and B to depend on spring-webmvc 5.3.9. In fact, we want our all projects to depend on the same version.
Thank you

Sometimes we have to change our code to use the new dependency.
Sometimes we don't have enough time to test and cause exceptions in
product environment, like NoSuchMethodError.
This sentence sounds like you have bad practices inside your organisation. You should put in place a solid policy on your testing and deployment (CI/CD) process.
A good practice is to implement a BOM or a parent POM project that will manage all your common dependencies. It is very good when it comes to manage and centralize your librairies versions.
Before any changes goes to the production server, it should be tested
You have to define a process for your tests : unit test > integration tests > end-to-end test
Every new implementation should pass pull/request and review process
Try to implement AGILE workflow in your team
My answer is not a silver bullet approach but I hope it will help you quite a lot. It is clearly an organisation issue that you have in your team or your enterprise. You have to implement Software Development Process.

Related

which dependencies can be suppressed and which cannot ? on a maven dependency check

How do I know which dependencies I need to suppress? Basically, what makes the difference in the dependencies that are not relevant to those that are?
an example would be extremely helpful.
I would strongly discourage you from asking security related questions here: you are not looking for financial advices on SO, the same applies for security - hire security expert and route all such questions to him.
In regards to dependency-check-maven from OWASP:
It is a bad idea to embed it into build lifecycle the way that it fails the build if vulnerable dependencies have been found (failBuildOnAnyVulnerability, failBuildOnCVSS, etc), otherwise it may suddenly stop the entire SDLC, but developers are not responsible for SEC stuff. Reporting is OK though - just give SEC guys a chance to participate in SDLC via reviewing reports and giving suggestions
If dependency-check-maven did find nothing it does not mean the application is not vulnerable at the current moment and won't be vulnerable in the future - unfortunately, security is not a state but a process, that in turn means you need to perform such checks periodically, i.e. either maintain CMDB with detailed information about installed applications and perform checks against that CMDB or use dependabot or other tools.
dependency-check-maven uses NVD database as a source of information about vulnerabilities, unfortunately neither NVD nor MITRE are actually performing security analysis - they just maintain database, that causes some dumb cases when researcher reports "vulnerability" which is actually not a vulnerability, some examples: CVE-2021-31684, CVE-2022-26520, however, investigating such cases is not a developer responsibility
If you have the time, you can remove all the dependencies from your pom, keeping them aside in a .bak file.
Of course, the compilation will fail,
but then you add them back, one by one, and only the one Maven build is complaining about their lack.
Then you execute and check that everything in your application is still working well.
That way, you seldom remove two or three dependencies when the project is very old.
Each Maven dependency can provide some of transitive dependencies.
Each used dependency in your project is relevant, simply project will not compile without it. Some of dependencies can be needed in runtime by your project.
You can read about Maven Dependency Mechanism and how to exclude dependencies.
You can also examine output of:
mvn dependency:analyze
mvn dependency:tree
Please familiarize yourself with documentation of Maven Dependency Plugin

Solution to dependency injection in ANT and EJB 3.0 for unit testing

I'm not a very experienced software engineer. We have a very large application that consists of 40 plus projects. We use EJB 3.0, Struts 1 framework.
Right now, we have issue unit testing Service layers having dependency on more than one beans. Because we can only inject one of them without a running server due to not having a container.
I've read that EJB3.1 does not have this issue. What changes in EJB3.1 has made it immune to this problem?
Also if you can direct me to a work around or a solution, I'd really appreciate it.
Another solution is to move from ANT to Maven, but I read in another question that it's not a good idea for very big projects like ours.
So my questions are:
Is there absolutely no solution to this?
What makes this dependency injection issue for unit testing work in Spring and Maven?
If giving multiple solutions, would appreciate it if you could also tell the scope of the changes required for the solution and effort it requires in phases of the project in general (analysis, design, testing, implementation, etc.)
Maven is definitely better than ant, and well used for big projects.
You can mock in dependencies, during unit tests.
EJB3.1 provides an embeddable container, which makes it easy to perform integration tests.

Spring profiles - risky code in svn

We are developing a project with spring framework.
we are using a tomcat cluster and in order to do some really advanced integration tests we added some controllers to the web app that are allowing some risky stuff that must not reach the production.
What we learned is that in order to do so we can use spring profiles and annotate the risky controllers as with the
#profile("Staging")
This annotation makes sure the bean will be created only when the active profile is "Staging".
Call me paranoid but this risky code now resides on our svn and is part of the project code.
It seems that the slieghtest mistake can lead to this code be part of production and allowing risky actions for exploiters.
moreover if some programmer forgets to annotate the code will reach the production for sure.
we all make mistakes.
Is there any mitigation for this issue?
I'll call you a bit paranoid. (wink) Hopefully you also have integration tests in your application, and they usually set up some of the environment - if they ever were to run in a production environment, they would probably screw up your database, send messages to other systems, etc.
You you don't worry about that. Why? Maybe you can use the answer to that to answer how you should package those risky pieces of code.
My suggestion: keep all the risky code in a single module (if you are using a multi-module build). Don't include this module in the production build (you can use maven profiles for that)
Or.. let the code check for itself whether it is allowed to run. Perhaps it can check for the presence of a certain file on the file system that you only create in your test environment.
It depends really on what you worry about.
But it is good to think about it. I know stories where load testing resulted in many orders being placed in an actual (external) order processing system.
The mistake you are speaking about is adding staging to list of active profiles. Yes, it is easy to do this. However it is easy to remove files from file system format the hard disk and turn the electricity off. So, your question really sounds as a kind of paranoia... :)
I think that the problem is not in Spring profiles but in your development methodology. If you are not sure in some code it should not be in production at all. How to achieve this? Move from svn to git. And start using branches. Each task is a branch. Without exceptions. Each task must be tested. So you can deploy every branch you want to staging, test it and when you are sure that the code is ok merge/rebase it to master. Master should be tested as well, and then can be deployed to production.
In this case you do not need profile "staging".

How to separate class loader for different jar version?

I have a test war file that contains many tests. Each test is packaged in maven project with a lot of dependencies. We use maven for dependency management but it comes with a problem. When a test update a common library, it can break other test that depends on the older version of the lib. How to make all the test run in a completely separate environment with its own set of library version? I can't execute them in a separate jvm because these tests need to be executed very frequently like very 30 sec or so. Can OSGi help solve this problem?
Yes OSGi can solve this problem, but it is not a step to be taken lightly. Use OSGi when you are ready to commit time and effort to isolating and managing dependencies, versioning them properly and, optionally, making your code and architecture more modular/reusable.
Bear in mind that adopting OSGi can be painful at first due to non-modular practices used by some legacy libraries.

A tool to detect broken JAR dependencies on class and method signature level

The problem scienario is as follows (Note: this is not a cross-jar dependency issue, so tools like JarAnalyzer, ClassDep or Tattletale would not help. Thanks).
I have a big project which is compiled into 10 or more jar artifacts. All jars depend on each other and form a dependency hierarchy.
Whenever I need to modify one of the jars, I would check out the relevant source code and the source code for projects that depend on it. Modify the code, compile, repackage the jars. So far so good.
The problem is: I may forget to check one of the dependent projects, because inter-jar dependencies can be quite long, and may change with time. If this happens some jars may go "out-of-sync" and I will eventually get a NoSuchMethodException or a some other class incompatibility issue at run-time, which is what I want to avoid.
The only solution I can think of, the most straighforward one, is to check out all projects, and recompile the bunch. But this takes time, especially if I re-build it every small change. I do have a continuous integration server, that could do this for me, but it's shared with other developers, so seeing if the build breaks is not an option for me.
However, I do have all the jars so hypothetically it should be possible to verify jars which depend on the code that I modified have an inconsistency in method signature, class names, etc. But how could I perform such check?
Has anyone faced a similar problem before? If so, how did you solve it? Any tools or methodologies would be appreciated.
Let me know if you need clarification. Thanks.
EDIT:
I would like to clarify my question a little bit.
The ultimate goal of this task is to check that the changes that I have made will compile against the whole project. I am looking for a tool/technique that would aid me perform such check.
Consider this example:
You have 2 projects: A and B which are deployed as A.jar and B.jar respectively. A depends on B.
You wish to modify B, so you check it out and modify a method signature that A happens to depend on. You can compile B and run all tests by itself without any problems because B itself does not depend on anything. So you happily commit your changes.
In a few hours the complete project integration fails because A could not be compiled!
How do I avoid this?
The kind of tool I am looking for would retrieve A.jar and check that all dependencies in A on the new modified B are still fine. Like a potential compilation error that would happen if I were to recompile A and B sources together.
Another solution, as was suggested by many of you, is to set up a local continuous integration system that would recompile the whole project locally. I don't mind doing this, but I want to avoid doing it inside my workspace. On the other hand, if I check-out all sources to another temporary workspace, then I need to mirror my local changes to the temporary workspace.
This is quite a big issue in my team, as builds break very often because somebody forgot to check out (or open in Eclipse) the right set of projects. I tried persuading people to check-out source and recompile the bunch before commits, but not only it takes time, it needs running quite a few commands so most people just find it too troublesome to do. If the technique is not easy or automated, then it's unusable.
If you do not want to use your shared continuous integration server you should set up a local one on your developer machine where you perform the rebuild processes on change.
I know Jenkins - it is easy to setup (just start) on a local machine and I would advice to run it locally if no one is provided in the IT infrastructure that fits your needs.
Checking signatures is unfortunately not enough. Having the correct signatures does not mean it'll work. It's all about contracts and not just signatures. I mean what happens if the new version of a library has the same method signature, but accepts an ArrayList parameter now in reversed order? You will run into issues - sooner or later. I guess you maybe consider implementing tools like Ivy or Maven:
http://ant.apache.org/ivy/
http://maven.apache.org/
Yes it can be pain to implement it but once you have it it will "guard" your versions forever. You should never run into such an issue. But even those build tools are not 100% accurate. The only proper way of dealing with incompatible libraries, I know you won't like my answer, is extensive regression testing. For this you need bunch of testing tools. There are plenty of them out there: from very basic unit testing (JUnit) to database testing (JDBC Proxy) and UI testing frameworks like SWTBot (depends if your app is a web app or thick client).
Please note if your project gets really huge and you have large amount of dependencies you always not using all of the code there. Trying to check all interfaces and all signatures is way too much. Its not necessary to test it all when your code use lets say 30 % of the library code. What you need is to test what you really use. And this can be only done with extensive regression testing.
I have finally found a whole treasure box of answers at this post. Thanks for help, everyone!
The bounty goes to K. Claszen for the quickest and most input.
I'm also think that just setup local Jenkins is a best idea. What tool you use for build? Maybe you can improve you situation with switching to Maven as build tool? In more smart and don't recompile full project if you don't ask it directly. But switch to in can be HUGE paint in the neck - it hardly depends on how you project organized now...
And about VCS- exist Mercurial/SVN bridge - so you can use local Mercurial for you development ....
check this link: https://www.mercurial-scm.org/wiki/WorkingWithSubversion
There is a solution, jarjar, which allows to have different versions of the same library to be included multiple times in the dependency graph.
I use IntelliJ, not Eclipse, so maybe my answer is too IDE-specific. But in IntelliJ, I would simply include the modules from B into A, so that when I make changes to A, it breaks B immediately when compiling in the IDE. Modules can belong to multiple projects, so this is not anything like duplication, it's just adding references in the IDE to modules in other projects.

Categories

Resources