Can I somehow ignore any warning for deprecated class?
For example:
I had following warnings AvoidEscapedUnicodeCharacters, NonEmptyAtclauseDescription for deprecated class.
How to ignore all of them?
Checkstyle allows you to write your own custom filters. You can use SuppressWarningsFilter as a basis, because this filter is filtering based on annotations as well. You'd just need to change the annotation that you're looking for.
public class SuppressWarningsFilter
extends AutomaticBean
implements Filter {
#Override
protected void finishLocalSetup() {
// No code by default
}
#Override
public boolean accept(AuditEvent event) {
return !SuppressWarningsHolder.isSuppressed(event);
}
}
Pretty simple, but all of the logic is in SuppressWarningsHolder. That code is a few hundred lines, but you should be able to copy and paste a lot of it, and probably remove a large chuck as well.
I've implemented this: https://github.com/michaelboyles/checkstyle-annotation-filter. I'll make it available via the central repository at some point.
You just need to add the line below:
#SuppressWarnings("deprecation")
It will ignore all deprecated methods in your code.
I hope this will help.
Related
I could not find much resources on my question so I guess this is not an easy resolution.
We use JodaTime in our codebase and I wish to forbid (or at least warn) using some methods from this library as they are prone to errors (around timezone management).
I tried the reflections library already, without success due to a non released issue.
We used to have a custom sonar rule to handle this but it is not supported by sonarcloud so I looking for another way.
Do you have any lead to handle this?
I would recommend using ArchUnit for this, which allows you to specify restrictions such as this as unit tests:
public class DisallowedMethodsTest {
#Test
public void forbidJodaTimeMethods()
{
JavaClasses importedClasses = new ClassFileImporter().importPackages("your.base.package");
ArchRule rule = noClasses().should()
.callMethodWhere(target(name("disallowedMethodName"))
.and(target(owner(assignableTo(DateTime.class)))))
.because("Your reasons");
rule.check(importedClasses);
}
}
If you are looking for something works in unit test environment, Jeroen Steenbeeke' answer might be helpful.
If you are looking for something works in production environmen, you'll need HOOK.
In case you cannot require partners to use java.lang.reflect.Proxy to construct related object, I'd recommend you have a look on AspectJ if you are working on a regular Java project or Xposed if you are working on an Android project.
Both of them could add restrictions without modifing existing codebase nor programming flow.
I solved such kind of problems by writing an interceptor like the following, as explained at https://docs.oracle.com/javaee/7/tutorial/interceptors002.htm:
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class MethodCallTracerInterceptor {
#AroundInvoke
Object intercept(InvocationContext context)
throws Exception
{
Method method = context.getMethod();
String methodClass = method.getDeclaringClass().getName();
String methodName = method.getName();
if (methodClass.equals("myClass") && methodName.equals("myMethod")) {
//TODO Raise an exception or log a warning.
}
return context.proceed();
}
}
If I wanted to keep a certain Java package free of 3rd party dependencies with ArchUnit, how would I do it?
More specifically I am looking at keeping my domain model in a hexagonal architecture free from spring code. I specified some rules which I believe ought to prevent the model from using spring. However, I am able to use spring annotations like #Component and #Bean without causing a violation.
What I tried so far is
layeredArchitecture().
layer("domain").definedBy(DOMAIN_LAYER).
layer("application").definedBy(APPLICATION_LAYER).
layer("primary-adapters").definedBy(PRIMARY_ADAPTERS).
layer("secondary-adapters").definedBy(SECONDARY_ADAPTERS).
layer("spring").definedBy("org.springframework..")
whereLayer("spring").mayOnlyBeAccessedByLayers("primary-adapters", "secondary-adapters", "application").
because("Domain should be kept spring-free").
check(CLASSES);
As well as
noClasses().that().resideInAPackage(DOMAIN_LAYER).
should().dependOnClassesThat().resideInAPackage("org.springframework..").
check(CLASSES);
noClasses().that().resideInAPackage(DOMAIN_LAYER).
should().accessClassesThat().resideInAPackage("org.springframework..").
check(CLASSES);
Here a code example which executes the tests just fine, although com.example.app.domain.Factory is importing org.springframework....
You can use DescribedPredicate:
void domainSpring() {
DescribedPredicate<JavaAnnotation> springAnnotationPredicate = new DescribedPredicate<JavaAnnotation>("Spring filter") {
#Override
public boolean apply(JavaAnnotation input) {
return input.getType().getPackageName().startsWith("org.springframework");
}
};
classes().that().resideInAPackage(DOMAIN_LAYER).should()
.notBeAnnotatedWith(springAnnotationPredicate).check(CLASSES);
}
You can also go with name matching.
So you don't have to write a custom DescribedPredicate.
ApplicationCoreMustNotDependOnFrameworks = noClasses()
.that().resideInAnyPackage(DOMAIN_LAYER)
.should().dependOnClassesThat().haveNameMatching("org.springframework.")
.orShould().dependOnClassesThat().haveNameMatching("javax.persistence.*")
.because("Domain should be free from Frameworks");
in my case, I wanted an exception to that rule.
I.e., instead of excluding completely Spring, I wanted to accept the classes in the event package (EventHanlder)
so you can replace "org.springframework" with "org.springframework(?!.*event).*" which is a regular expression
Let's say I've an implementation of fund transfer. Now I want to add authentication functionality which should be done before fund transfer (considering we are already receiving username and password in existing request). Which pattern should we use and how we can achieve this without modifying calling class and existing implementation?
What I can think of at this moment is using decorator pattern after extending implementation class, but I believe still we will be required to modify the calling class.
Please find existing Interface and classes.
package sb.test.demo.fundtransfer;
public interface FundTransferService {
public boolean makeTransfer(TransferRequest request) throws Exception;
}
package sb.test.demo.fundtransfer;
public class FundTransferServiceImpl implements FundTransferService {
#Override
public boolean makeTransfer(TransferRequest request) throws Exception {
//Dummy Code
System.out.println("TransferDone");
return true;
}
}
package sb.test.demo.fundtransfer;
public class TestTransfer {
public static void main(String[] args) throws Exception {
TransferRequest request = new TransferRequest();
request.setSourceAccount(123456);
request.setDestinationAccount(654321);
request.setTranserAmount(1000);
request.setUserName("user1");
request.setPassword("pass1");
FundTransferService fts = new FundTransferServiceImpl();
fts.makeTransfer(request);
}
}
Now, I want want extend FundTransferServiceImpl to createFundTransferServiceNEWImpl which will add authentication.
package sb.test.demo.fundtransfer;
public class FundTransferServiceNEWImpl extends FundTransferServiceImpl {
#Override
public boolean makeTransfer(TransferRequest request) throws Exception {
//Dummy Code
System.out.println("Authenticating..");
super.makeTransfer(request);
System.out.println("TransferDone from NEW..");
return true;
}
}
Now, without changing TestTransfer.java and FundTransferServiceImpl.java how can I invoke makeTransfer of FundTransferServiceNEWImpl to add authentication? Or, is there any other way to achieve the same?
Please can anyone help me on this?
Thanks in advance!
you can make "FundTransferServiceNEWImpl" also implement the interface "FundTransferService" and provide the implementation that you wish in this only, if this was what you asked for!!
Now, without changing TestTransfer.java and FundTransferServiceImpl.java how can I invoke makeTransfer of FundTransferServiceNEWImpl to add authentication?
You can't without changing the bytecode of either TestTransfer (the caller) or FundTransferServiceImpl (the callee).
There are two ways to change the bytecode.
You can
edit the source file and compile
edit the bytecode before the class is loaded
Edit the source file
I would suggest to edit the TestTransfer class. The problematic line is
FundTransferService fts = new FundTransferServiceImpl();
because this line introduces the dependency from TestTransfer to FundTransferServiceImpl.
I would also suggest to implement the decorator by composition and not inheritence. E.g.
public class AuthenticationFundTransferServiceWrapper implements FundTransferService {
private FundTransferService fundTransferService;
public AuthenticationFundTransferServiceWrapper(FundTransferService fundTransferService){
this.fundTransferService = fundTransferService;
}
public boolean makeTransfer(TransferRequest request) throws Exception {
//Dummy Code
System.out.println("Authenticating..");
fundTransferService.makeTransfer(request);
System.out.println("TransferDone from NEW..");
return true;
}
}
The advantage is that the AuthenticationFundTransferServiceWrapper does only depend on the interface FundTransferService and not the implementation. This reduces dependencies and makes the class more flexible.
Editing the byte code
Editing the bytecode before the class is loaded is possible.
Take a look at
AOP (aspect oriented programming)
AspectJ
ASM (bytecode manipulation)
cglib
So you've identified decorator pattern and this answer implemented decorator correctly, but as this is a SOLID principles question I'm going to point out the flaw in that option.
To see the flaw in either inheritance or decorator, consider what happens when the authorization fails. If it throws a new exception type, that is a Liskov Substitution Principle Violation. If it changes the behavior by silently not transferring the funds, that is also an LSP violation. If you're going to rely on the boolean returned, you're not going to get a useful failure message back to the user or system admin.
As I see it, there is no way the client code can avoid knowing that the new implementation is checking authorized as it needs to handle either a new exception, or different return values.
Given that, I would recommend you add a new class, like this:
public final class TransactionAuthorizationService {
private final FundTransferService fundTransferService;
public AuthenticationFundTransferServiceWrapper(FundTransferService fundTransferService){
this.fundTransferService = fundTransferService;
}
public boolean authorizeAndMakeAndTransfer(TransferRequest request) throws Exception {
//Dummy Code
System.out.println("Authenticating..");
fundTransferService.makeTransfer(request);
System.out.println("TransferDone from NEW..");
return true;
}
}
Advantages:
Where before client code dealt with the interface FundTransferService you would have no idea until runtime which implementation they had and whether they would be authorizing transactions, now the client code now deals with the TransactionAuthorizationService and they call authorizeAndMakeAndTransfer so it is very clear.
As our new class is not implementing an existing interface, there is no Liskov Substitution Violation and is free to return different values or throw different exceptions.
Other tips:
Stop decorating methods with throw alls: throws Exception
Don't use InterfaceImpl as class names, look for what makes them concrete over the abstract interface.
So, here's an example. I have a library in the package HTTP. I define sub-sections of the library in e.g. the package HTTP.TCPProtocol. Now I want to use TCPProtocol from the HTTP package, which means I have to make the TCPProtocol functionality public. At the same time, this functionality should not be exported to users of the library.
How do I do this? I don't want to shove my whole library into one package, as I feel the separate sub-packages really make the code more structured and navigation easier in eclipse. But browsing around, I couldn't find a method to expose functions within my project, but not export them outside my project.
EDIT: In light of me being able to come up with a better example, I'm updating the OP.
One simplistic approach is to whitelist your 'utility' methods so they take a caller instance of a certain type only.
package gameengine;
interface Whitelisted {} // marker
Then your method:
public void myMethod(Whitelisted caller, String arg)
And to invoke:
package gameengine.network;
class Foo implements Whitelisted {
...
Someclass.myMethod(this, "foo");
Check the caller's class to lock out all unwanted callers. The caller's class can be obtained from the stacktrace. In the example below, only instances of Bar will trigger the system.out.println, all all other will get an exception. You can even do package-level checks this way. Make sure that all allowed caller classes methods are not public, or they can call the doSomething method indirectly. You can even do deeper checks, by inspecting the stacktrace further.
Be aware though, that a skilled develper can circumvent anything you try do do in this matter. No solution is really "secure".
package one.two;
import one.Bar;
public class Foo {
public void doSomething() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
StackTraceElement stackTraceElement = stackTrace[2];
String className = stackTraceElement.getClassName();
if (Bar.class.getName().equals(className)) {
System.out.println("jay!");
} else {
throw new RuntimeException("not allowed");
}
}
}
package one;
import one.two.Foo;
public class Bar {
void makeCall() {
new Foo().doSomething();
}
public static void main(String[] args) {
new Bar().makeCall();
}
}
Without seeing your dependencies, the only real advice the community can give you is to refactor your code. If something in your networking package needs to know about your game engine, it seems like you have a leaky abstraction. Hard to say without seeing your code.
This is my first post here, recently i have been working with JSF2.0 with primefaces. we have this requirement to export PDF in our application. initially we used primefaces default dataexporter tag. but the format was simply terrible. so, i used itext to generate PDF. we have like upto 15 datatables in our app, and all of them require PDF exporting. i have created a method called generatePDF which creates the PDF using Itext for all the tables.
Interface PDFI {
public void setColNames();
public void setColValues();
public void setContentHeader();
}
Class DataEx {
public void generatePDF(ActionEvent event) {
// generate pdf...
}
}
consider i have a Datatable A in the view
Datatable A ...
bean behind this datatable..
Class BeanA implements PDFI {
//implemented methods
}
}
Class BeanB implements PDFI {
//implemented methods
}
and behind another datatable B, i do the same thing as above ..
so, my question here is, is this considered duplicate code ?? and also, is this the efficient way to do this.
any help is appreciated.
thanks ina dvance
Rule of thumb that I use before re-factoring duplicate code- when part of the code in one place have a bug- are you need to change the other one to? cause you probably will forget
in your case, it's look like you have duplicate code block. I'll consider add the require parameters to generatePDF so it'll do all work in one place.