I have this warning on most of my classes and not sure why is that. This happens on both public normal classes and final classes which have private constructors, some no constructor at all. I tried changing my private class methods to protected, doesn't help. Any suggestions on how to turn this off?
Here's a class example
public final class PlanBenefitManagerAssembler {
private static final Logger LOGGER = Logger.getLogger(PlanBenefitManagerAssembler.class);
/**
* No Instance of the this class is allowed.
*/
private PlanBenefitManagerAssembler() {
}
public static List<BenefitDecisionDetailsBean> assembleBenefitDecisionDetailsBean(
List<BenefitDetails> benefitDecisionDetailsList, int relationalSequenceNumber) {
LOGGER.debug("Enter assembleBenefitDecisionDetailsBean");
List<BenefitDecisionDetailsBean> benefitDecisionDetailsBeanList = new ArrayList<BenefitDecisionDetailsBean>();
for (BenefitDetails benefitDecisionDetails : benefitDecisionDetailsList) {
BenefitDecisionDetailsBean benefitDecisionDetailsBean = new BenefitDecisionDetailsBean();
benefitDecisionDetailsBean.setBenefitTypeCode(benefitDecisionDetails.getBenefitTypeCode());
benefitDecisionDetailsBean.setRelationSequenceNumber(relationalSequenceNumber);
benefitDecisionDetailsBean.setBenefitStatusDescription(
benefitDecisionDetails.getBenefitStatusDescription());
benefitDecisionDetailsBean.setBenefitStatusCode(benefitDecisionDetails.getBenefitStatusCode());
benefitDecisionDetailsBean.setBenefitUnderwritingStatusCode(
benefitDecisionDetails.getBenefitUnderwritingStatusCode());
benefitDecisionDetailsBean.setBenefitUnderwritingStatusDescription(
benefitDecisionDetails.getBenefitUnderwritingStatusDescription());
benefitDecisionDetailsBean.setBenefitChangeReasonCode(
String.valueOf(benefitDecisionDetails.getBenefitChangeReasonCode()));
benefitDecisionDetailsBean.setBenefitChangeReasonDescription(
benefitDecisionDetails.getBenefitChangeReasonDescription());
benefitDecisionDetailsBean.setComponentNumber(benefitDecisionDetails.getBenefitNumber());
benefitDecisionDetailsBean.setBenefitVisible(benefitDecisionDetails.isExplicitBenefitDecisionRequired());
benefitDecisionDetailsBean.setModelChanged(false);
// * Set BenefitLoading and BenefitExclusion
List<ExclusionDetailsBean> exclusionDetailsBeanList =
PlanBenefitManagerAssembler.assembleExclusionDetailsList(benefitDecisionDetails
.getBenefitExclusionsDetailsList().getBenefitExclusionsDetailsList());
List<LoadingDetailsBean> loadingDetailsBeanList =
PlanBenefitManagerAssembler.assembleLoadingDetailsList(benefitDecisionDetails
.getBenefitLoadingsDetailsList().getBenefitLoadingsDetailsList());
benefitDecisionDetailsBean.setExclusionDetailsBeanList(exclusionDetailsBeanList);
benefitDecisionDetailsBean.setLoadingDetailsBeanList(loadingDetailsBeanList);
benefitDecisionDetailsBeanList.add(benefitDecisionDetailsBean);
}
LOGGER.debug("Exit assembleBenefitDecisionDetailsBean");
return benefitDecisionDetailsBeanList;
}
}
When Checkstyle produces a warning the warning text should include a short rule name which will allow you to look up the exact rule that is being triggered. "DesignForExtension", for example.
Given the rule name, you can look up more detail on what it means in the Checkstyle documentation: http://checkstyle.sourceforge.net/availablechecks.html
Post the full details of the rule being triggered and someone might be able to help.
You can always turn the warnings off, but they generally are here for a reason :)
Do you intend to make them abstract classes ? If so, declare them that way.
Will you need to instantiate them at some point ? If so, add a public constructor.
I'm pretty sure this will solve your problem.
On sourceforge it says that the AbstractClassName rule uses the following regex:
^Abstract.*$|^.*Factory$
This causes classes with a name starting with 'Abstract' or ending with 'Factory' to be flagged. I get the 'Abstract..' part of that, but why should all '..Factory' classes be abstract? Sometimes I create factories which use dependencies to do their work so I need an instance to inject into.
This however does not explain your case. I tried your example class and did not get any Checkstyle warning (I am using the Eclipse Checkstyle Plug-in version 5.3.0.201012121300).
Are you sure you are getting the AbstractClassName warning for this class? Which version of Checkstyle are you using?
Related
I have an interface with a default method and a private method, where the private method is called from the default method.
When running Spotbugs, it issues an error that the private method is never called: UPM_UNCALLED_PRIVATE_METHOD.
public interface Foo {
default boolean foo(int value1, int value2) {
return bar(value1 + value2);
}
private boolean bar(int value) {
return value == 0;
}
}
I'm doing something wrong or it's a Spotbugs issue?
Note 1: When modifying the private method to static, it doesn't report the error.
Note 2: I've seen similar issues reported, but all are closed and related to class instead of interface.
UPDATE
A similar issue was recently reported on Github (#1988), but hasn't been solved yet.
Spotbugs 4.5.3 reports this as "low priority" bug.
IMHO you have basically two options:
report it to the Spotbugs project as issue (https://github.com/spotbugs/spotbugs/issues)
tell Spotbugs to ignore the problem:
either annotate the method with #SuppressFBWarnings("UPM")
or use a filter file (https://spotbugs.readthedocs.io/en/stable/filter.html)
The solution with the annotation is probably easier to implement but clutters your source code.
The solution with the filter file might be harder to implement (if you do not use a filter file already) and the connection between the actual code and the filter might get lost, but your source code is not cluttered with annotations just to mute a noisy tool.
As I installed Sonarlint plugin in my eclipse IDE, i got the above (Heading) Major Issue in Sonar Report.
The Code is:
public class Demo
{
public static final Map<String, String> CARD_TYPES;
static
{
CARD_TYPES = new HashMap<String, String>()
{
{ //Move the contents of this initializer to a standard constructor or to field* initializers
put("visa", "001");
put("diner", "002");
}
};
}
//..code goes here
}
The Query is: what exactly should be done in above Static Block, to
Resolve the above issue ?
Your code example seems to be altered for this post? Doesn't compile because CARD_TYPES is not declared anywhere. Also there is a * in front of the inline comment which shouldn't be there.
Regardless, in your SonarLint report you can select a specific issue.
which then allows you to see the details of the Rule that it is reporting this issue.
These descriptions also contain compliant and not compliant code examples to help you understand the issue. In your case a compliant solution would be.
Basically: initialize the map directly at the declaration. Then use the static context of the class to access and fill it, rather than the context of the map.
I am working with AspectJ at the moment.
I seperated AspectJ code in a dependency.
Within that dependency everything works as intended.
But as soon as I import it in another project only some functionality does not work anymore.
When using the defaultImpl of #DeclareParents, the interface is shown within the compiled code but not the default Implementation.
Here is my code to show what I mean (every code snippet is its own File):
AspectJ code:
public interface IAspect
{
String hello();
}
public class IAspectDefaultImpl implements IAspect
{
#Override
public String hello()
{
return "hello";
}
}
#Aspect
public class AspectJ
{
#DeclareParents(value = "#SomeAnnotation*", defaultImpl = IAspectDefaultImpl.class)
private IAspect implementedInterface;
}
Target Class in a different project:
#SomeAnnotation
public class MyClass
{
private final int myValue;
public MyClass(final int wert)
{
this.myValue = wert;
}
public int getMyValue()
{
return myValue;
}
}
Maven throws me:
The type MyClass must implement the inherited abstract method IAspect.hello()
Which implies that it works partially.
When looking at the decompiled .class files the targeted Class does in fact implement IAspect.
The method defined in IAspectDefaultImpl is still missing tho.
My pom is set up like in this example.
I am not sure where I should start to look for errors.
Any help is apreciated.
Thanks for the MCVE. But hey, you don't use Git in order to commit 7z or ZIP archives, you ought to commit source code. I forked your project and fixed that, restructured and simplified your POMs and also fixed the main problem.
See my pull request and the commits in it for further details.
Concerning your problem, I can confirm that it occurs if you use #DeclareParents the way you do in an aspect library.
Actually, according to AspectJ maintainer Andy Clement there are certain problems with #DeclareParents when using it to provide parent interfaces + implementations in annotation style. The native AspectJ syntax via declare parents is not affected by that, but for annotation-style syntax Andy provided an alternative called #DeclareMixin, see the AspectJ manual. There he mentions that he is even considering to deprecate the defaultImpl argument of #DeclareParents in favour of #DeclareMixin.
So my bugfix (or workaround) for your problems is to actually replace
#DeclareParents(value = "#de.example.aspect.SomeAnnotation *", defaultImpl = IAspectDefaultImpl.class)
private IAspect implementedInterface;
by
#DeclareMixin("#de.example.aspect.SomeAnnotation *")
public static IAspect createIAspectImplementation() {
return new IAspectDefaultImpl();
}
This works with aspect libraries.
I will discuss with Andy about whether it makes sense to file a bug ticket for your problem or if he won't fix it anyway because there is a viable and recommended alternative.
I woud like to write a JUnit test to verify that the code below uses a BufferedInputStream:
public static final FilterFactory BZIP2_FACTORY = new FilterFactory() {
public InputStream makeFilter(InputStream in) {
// a lot of other code removed for clarity
BufferedInputStream buffer = new BufferedInputStream(in);
return new CBZip2InputStream(buffer);
}
};
(FilterFactory is an interface.)
My test thus far looks like this:
#Test
public void testBZIP2_FactoryUsesBufferedInputStream() throws Throwable {
InputStream in = mock(InputStream.class);
BufferedInputStream buffer = mock(BufferedInputStream.class);
CBZip2InputStream expected = mock(CBZip2InputStream.class);
PowerMockito.spy(InputHelper.BZIP2_FACTORY); // This line fails
whenNew(BufferedInputStream.class).withArguments(in).thenReturn(buffer);
whenNew(CBZip2InputStream.class).withArguments(buffer).thenReturn(expected);
InputStream observed = InputHelper.BZIP2_FACTORY.makeFilter(in);
assertEquals(expected, observed);
}
The call to PowerMockito.spy raises an exception with this message:
org.mockito.exceptions.base.MockitoException:
Mockito cannot mock this class: class edu.gvsu.cis.kurmasz.io.InputHelper$1
Mockito can only mock visible & non-final classes.
What should I be using instead of PowerMocktio.spy to set up the calls to whenNew?
The message is pretty obvious: You can't mock non-visible and final classes. Short answer : Create a named class of your anonymous one, and test this class instead!
Long answer, let's dig why !
An anonymous class is final
You instantiate an anonymous class of FilterFactory, when the compiler sees an anonymous class, it creates a final and package visible class. So the anonymous class is not mockable through standard mean i.e. through Mockito.
Mocking anonymous class : possible but BRITTLE if not HACKY
OK, now suppose you want to be able to mock this anonymous class through Powermock. Current compilers compile anonymous class with following scheme :
Declaring class + $ + <order of declaration starting with 1>
Mocking anonymous class possible but brittle (And I mean it)
So supposing the anonymous class is the eleventh to be declared, it will appear as
InputHelper$11.class
So you could potentially prepare for test the anonymous class:
#RunWith(PowerMockRunner.class)
#PrepareForTest({InputHelper$11.class})
public class InputHelperTest {
#Test
public void anonymous_class_mocking works() throws Throwable {
PowerMockito.spy(InputHelper.BZIP2_FACTORY); // This line fails
}
}
This code will compile, BUT will eventually be reported as an error with your IDE. The IDE probably doesn't know about InputHelper$11.class. IntelliJ who doesn't use compiled class to check the code report so.
Also the fact that the anonymous class naming actually depends on the order of the declaration is a problem, when someone adds another anonymous class before, the numbering could change.
Anonymous classes are made to stay anonymous, what if the compiler guys decide one day to use letters or even random identifiers!
So mocking anonymous classes through Powermock is possible but brittle, don't ever do that in a real project!
EDITED NOTE : The Eclipse compiler has a different numbering scheme, it always uses a 3 digit number :
Declaring class + $ + <pad with 0> + <order of declaration starting with 1>
Also I don't think the JLS clearly specify how the compilers should name anonymous classes.
You don't reassign the spy to the static field
PowerMockito.spy(InputHelper.BZIP2_FACTORY); // This line fails
whenNew(BufferedInputStream.class).withArguments(in).thenReturn(buffer);
whenNew(CBZip2InputStream.class).withArguments(buffer).thenReturn(expected);
InputStream observed = InputHelper.BZIP2_FACTORY.makeFilter(in);
PowerMockito.spy returns the spy, it doesn't change the value of InputHelper.BZIP2_FACTORY. So you would need to actually set via reflection this field. You can use the Whiteboxutility that Powermock provide.
Conclusion
Too much trouble to just test with mocks that the anonymous filter uses a BufferedInputStream.
Alternative
I would rather write the following code:
An input helper that will use the named class, I don't use the interface name to make clear to the user what is the intent of this filter!
public class InputHelper {
public static final BufferedBZIP2FilterFactory BZIP2_FACTORY = new BufferedBZIP2FilterFactory();
}
And now the filter itself :
public class BufferedBZIP2FilterFactory {
public InputStream makeFilter(InputStream in) {
BufferedInputStream buffer = new BufferedInputStream(in);
return new CBZip2InputStream(buffer);
}
}
Now you can write a test like this :
#RunWith(PowerMockRunner.class)
public class BufferedBZIP2FilterFactoryTest {
#Test
#PrepareForTest({BufferedBZIP2FilterFactory.class})
public void wraps_InputStream_in_BufferedInputStream() throws Exception {
whenNew(CBZip2InputStream.class).withArguments(isA(BufferedInputStream.class))
.thenReturn(Mockito.mock(CBZip2InputStream.class));
new BufferedBZIP2FilterFactory().makeFilter(anInputStream());
verifyNew(CBZip2InputStream.class).withArguments(isA(BufferedInputStream.class));
}
private ByteArrayInputStream anInputStream() {
return new ByteArrayInputStream(new byte[10]);
}
}
But could eventually avoid powermock stuff for this test scenario if you force the CBZip2InputStream to only accept BufferedInputStream. Usually using Powermock means something is wrong with the design. In my opinion Powermock is great for legacy softwares, but can blind developers when designing new code; as they are missing the point of OOP's good part, I would even say they are designing legacy code.
Hope that helps !
Old post, but you don't need to create a named class - use wildcards instead as mentioned in this post powermock mocking constructor via whennew() does not work with anonymous class
#PrepareForTest(fullyQualifiedNames = "com.yourpackage.containing.anonclass.*")
You need to run the test using the PowerMockito runner, and you need to tell the framework which class(es) should have custom behaviour. Add the following class annotations on your test class:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ BufferedInputStream.class })
I just came around the same problem. So according to the documentation of constructor mocking you need to prepare the class, which will create the evil class(es). In your case the evil classes are BufferedInputStream and CBZip2InputStream, and the creator of them is an anonymous class, which cannot be defined in PrepareForTest annotation. So I had to do the same as you did (hmm, just saw your comment), I moved the anonymous class to named class.
I'm getting an anonymous class at compile-time that I'm not expecting. Relevant code follows, then a more detailed explanation:
Entirety of CircuitType.java:
public enum CircuitType { V110A20, V110A30, V208A20, V208A30 }
From Auditor.java, lines 3-9:
public class Auditor {
private String[] fileNames;
private int numV110A20;
private int numV110A30;
private int numV208A20;
private int numV208A30;
From Auditor.java, lines 104-121:
[...]
switch (newCircuit.getType()) {
case V110A20:
this.numV110A20++;
break;
case V110A30:
this.numV110A30++;
break;
case V208A20:
this.numV208A20++;
break;
case V208A30:
this.numV208A30++;
break;
default:
System.err.println("An Error Has Occured.");
System.exit(-1);
break;
}
[...]
From Circuit.java, lines 1-5:
public class Circuit {
private CircuitType myType;
public CircuitType getType() {
return this.myType;
}
[...]
When the command
javac *.java
is executed, an anonymous class Auditor$1.java is generated. The files, obviously, all sit next to each other in a file system directory that contains nothing else.
When lines 104-121 are commented out, no anonymous class is generated.
I at first thought it was a package issue, so put the three classes in a package, but I didn't know enough about packages to get it working. If it's truely a package issue, can someone step me through exactly how to label them? I'd rather not have to package them if I don't have to, though.
The reason the anonymous class is a problem, besides the fact that such classes usually signify a namespace issue, is that it breaks my Makefile I use for automatic compilation.
Update
Attached is a console session which I hope may shed light on this mystery:
% javap 'Auditor$1'
Compiled from "Auditor.java"
class Auditor$1 extends java.lang.Object{
static final int[] $SwitchMap$CircuitType;
static {};
}
I've gone ahead and built a little project containing the source you posted and just enough framework around it to make it compile. I got 3 class files: Circuit.class, CircuitType.class and Auditor.class - as expected.
All this under Java 1.6. But as others have indicated, I think your diagnosis of the problem is off.
Anonymous classes are easy to generate accidentally: Typically a construct like
Circuit myCircuit = new Circuit() {
public CircuitType getCircuitType() {
return XXX;
}
}
will create one, for example. Given more of your code, the good SO folks might be able to pinpoint your error.
It might be interesting and instructive to disassemble your class files with javap or better yet a "real" Java disassembler like JD.
Update
Added your new Auditor code to mine... no change. No anonymous classes.
Your code is of course correct (to the extent we can see it) but the design is not very OO. Some people would point out that you'll have to extend your counter declarations and your switch statement every time a new circuit type appears.
You're also not making much use of the "special features" of enums. I have a much simplified version of your Auditor method:
private int[] counters = new int[CircuitType.values().length];
public void tallySomething() {
Circuit newCircuit = new Circuit();
counters[newCircuit.getType().ordinal()]++;
}
Update 2
I found your javap output quite illuminating. See my comment below.
My conclusions:
Yes, apparently your Java impl is using an anon class for the switch. Lame, but legitimate.
You have the following options:
eliminate the switch
use a different Java implementation
live with the anonymous class; ditch make and use ant to embrace the anon classes and other strangenesses of Java.
Since you're only having problems because of your non-standard compilation setup, I'd go with the last solution and attack the problem there.
It indeed appears that (in certain cases at least) an inner class will be generated for the switch statement:
Java enum and additional class files