mapstruct v1.3.1FINAL: imports from static methods aren't generated - java

We are using mapstruct 1.3.1FINAL (in combination with lombok v1.18.4 if that matters) and the generated classes aren't compiling because the imports of the static methods used in expression mappings aren't generated. Any clues?
#Mapping(target = "value", expression = "java(ValueUtil.getValue(sourceValue))")
The generated code has compilation errors because the import of ValueUtil is missing :
request.setValue( ValueUtil.getValue(sourceValue) );

Finally i got it, tried out what Sjaak wrote.
#Mapper(imports = { ValueUtil.class })
The import made it. Will try out if Deepaks answer works as well.

Please try with fully qualified class name for ValueUtil I.e. packagename.ValueUtil. This will provide the context to mapstruct to locate the class.

you can add an import statement to the #Mapper annotation, precisely for such cases. Checkout the documentation.

Related

Annotation type not applicable to this kind of declaration error in package info class in Java 8

I have a package info class, it used to compile in Java 6/7. But in Java 8, I get compilation errors:
*****error: annotation type not applicable to this kind of declaration
#NamedNativeQueries({
error: annotation type not applicable to this kind of declaration
#SqlResultSetMappings({*****
This is the code:
#NamedNativeQueries({
#NamedNativeQuery(name = "",
query = "",
resultSetMapping = "mapping"
),
NamedNativeQuery(
name = "",
query = "",
callable = true,
readOnly = false,
resultSetMapping = ""
)
})
#SqlResultSetMappings({
})
package abc.domain;
import javax.persistence.ColumnResult;
import javax.persistence.EntityResult;
import javax.persistence.FieldResult;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.SqlResultSetMappings;
Thanks in advance for your help
EDIT: Additional comments have made more clear what's going wrong here; as a consequence, the nature of this answer has changed somewhat.
It sounds like you switched from Hibernate's own version of #NamedNativeQueries and company, which you can stick on packages, to the general javax persistence variant, which cannot be placed on packages.
You must have removed and re-generated the imports in your attempt to convert this code. Don't do that - remove all those imports and replace them with import org.hibernate.annotations.NamedNativeQueries and friends instead.
For posterity, the original answer, still valid but only in context specifically for javax.persistence.NamedNativeQueries.
You must be misremembering; it does not and never has worked on java7 (that's the java7 docs of amedNativeQueries - note how it has a #Target(value=TYPE) marker, so it cannot be put on a package, and that's the v7 edition of the docs!)
You put such things on a type, for example the top level type. Which means the annotations appear near the top, but after the package statement. Given that you're using them in a package-info.java file, they simply cannot appear here (and never could).
SqlResultSetMappings is the same.
There's a small chance that somehow javac7 didn't actually check the Target condition of these annotations. However, that simply means that your code never worked, even if it did compile.

Obtaining the fully qualified name from an Annotation using Eclipse JDT AST

I am using the Eclipse JDT to build AST for Java source code, so I can do some code analysis. Currently I would like to obtain the fully qualified name of an annotation. Consider the code below:
import javax.persistence.Entity;
#Entity
public class Class1
If I visit this Compilation Unit, the #Entity is a MarkerAnnotation. And I can do some analysis on it. However I am unable to obtain the Fully qualified name. I would like to obtain "javax.persistence.Entiy". I have tried several ways, but with no success.
public boolean visit(MarkerAnnotation node) {
node.getTypeName(); //returns the simple name
node.getTypeName().getFullyQualifiedName();// I thought this would print javax.persistence.Entiy,
// but it only prints "Entity"
node.resolveTypeBinding().getName(); //Prints "Entity"
node.resolveTypeBinding().getBinaryName(); // Prints "Entity"
node.resolveAnnotationBinding().getName(); //Prints "Entity"
return super.visit(node);
}
I have also tried to cast MarkerAnnotation to Annotation, but I am still unable to get fully qualified name. During debugging sesssions, I had no success either navigating this node
I was able to get the fully qualified name using the imports() method of the CompilationUnit. I did some String manipulations on them, combining with the annotations simple name. However, I feel this is sort of hacky, and I need to look at every import, even ones that are not related to annotations.
What I would like is to obtain the fully qualified name directly from the node, i.e, from the MarkerAnnotation, NormalAnnotation and SingleMemberAnnotation. Is there any way to achieve this? What Am I missing here?
Thanks in advance!
From the javadoc of Annotation.resolveAnnotationBinding():
Note that bindings (which includes resolved annotations) are generally unavailable unless requested when the AST is being built.
So please check how you configure ASTParser, see ASTParser.setResolveBindings(boolean)

cannot resolved to a type error in java

I'm new in java, please help me to understand this.
I can see there is ReadHtml class and defined with one public method. But when i put this code in ecplise, it shows red mark under WebClient with tag that "this cannot resolved to a type". May I know what does it mean? Gone through all about method definition but couldn't find any remedy to understand this.
Can I get any help ?
public class ReadHtml {
public static LinkedList<String> readJacksonCounty(String urlName, String pStartDate,String pFinishDate)
{
LinkedList<String> xmlListReturn=new LinkedList<String>();
System.getProperties().put("org.apache.commons.logging.simplelog.defaultlog", "error");
final WebClient webClient1 = new WebClient(BrowserVersion.CHROME);
webClient1.setJavaScriptTimeout(60000);
webClient1.getCookieManager().setCookiesEnabled(true);//enable cookies
webClient1.getCache().clear();
You are missing an import of this library:
import com.gargoylesoftware.htmlunit.WebClient;
Add this to the top of your file (and read dsp_user's comment for future reference).
Basically "...cannot be resolved to a type" means that type is not available on the class path. If you're just using eclipse refere to How to import a jar in Eclipse.
If you already added the needed jar onto your class path, you are missing the import statement. Imports just make it so that you dont have to use a class's fully qualified name. (you can type
MyClass myClass;
as opposed to
com.some.package.MyClass myClass;
if you add
import com.some.package.MyClass;
at the top of your file.
Note that if you want to build a jar from your project you'll need some kind of build tool. If you choose to use Maven, which is very common, just read any tutorial on how to get started and manage dependencies.

How to scan multiple paths using the #ComponentScan annotation?

I'm using Spring 3.1 and bootstrapping an application using the #Configuration and #ComponentScan attributes.
The actual start is done with
new AnnotationConfigApplicationContext(MyRootConfigurationClass.class);
This Configuration class is annotated with
#Configuration
#ComponentScan("com.my.package")
public class MyRootConfigurationClass
and this works fine. However I'd like to be more specific about the packages I scan so I tried.
#Configuration
#ComponentScan("com.my.package.first,com.my.package.second")
public class MyRootConfigurationClass
However this fails with errors telling me it can't find components specified using the #Component annotation.
What is the correct way to do what I'm after?
Thanks
#ComponentScan uses string array, like this:
#ComponentScan({"com.my.package.first","com.my.package.second"})
When you provide multiple package names in only one string, Spring interprets this as one package name, and thus can't find it.
There is another type-safe alternative to specifying a base-package location as a String. See the API here, but I've also illustrated below:
#ComponentScan(basePackageClasses = {ExampleController.class, ExampleModel.class, ExmapleView.class})
Using the basePackageClasses specifier with your class references will tell Spring to scan those packages (just like the mentioned alternatives), but this method is both type-safe and adds IDE support for future refactoring -- a huge plus in my book.
Reading from the API, Spring suggests creating a no-op marker class or interface in each package you wish to scan that serves no other purpose than to be used as a reference for/by this attribute.
IMO, I don't like the marker-classes (but then again, they are pretty much just like the package-info classes) but the type safety, IDE support, and drastically reducing the number of base packages needed to include for this scan is, with out a doubt, a far better option.
Provide your package name separately, it requires a String[] for package names.
Instead of this:
#ComponentScan("com.my.package.first,com.my.package.second")
Use this:
#ComponentScan({"com.my.package.first","com.my.package.second"})
Another way of doing this is using the basePackages field; which is a field inside ComponentScan annotation.
#ComponentScan(basePackages={"com.firstpackage","com.secondpackage"})
If you look into the ComponentScan annotation .class from the jar file you will see a basePackages field that takes in an array of Strings
public #interface ComponentScan {
String[] basePackages() default {};
}
Or you can mention the classes explicitly. Which takes in array of classes
Class<?>[] basePackageClasses
You use ComponentScan to scan multiple packages using
#ComponentScan({"com.my.package.first","com.my.package.second"})
You can also use #ComponentScans annotation:
#ComponentScans(value = { #ComponentScan("com.my.package.first"),
#ComponentScan("com.my.package.second") })
I use:
#ComponentScan(basePackages = {"com.package1","com.package2","com.package3", "com.packagen"})
make sure you have added this dependency in your pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Use
#ComponentScan(basePackages = {"package1", "package2"})
define it at top before class.
Edit: the brackets must be around all the base packages, not a pair of brackets per package

Suppress deprecated import warning in Java

In Java, if you import a deprecated class:
import SomeDeprecatedClass;
You get this warning: The type SomeDeprecatedClass is deprecated
Is there a way to suppress this warning?
To avoid the warning:
do not import the class
instead use the fully qualified class name
and use it in as few locations as possible.
Use this annotation on your class or method:
#SuppressWarnings("deprecation")
Since Java 9, you might need to add:
#SuppressWarnings("removal")
If the class was annotated with something like:
#Deprecated(since = "3.14", forRemoval = true)
As a hack you can not do the import and use the fully qualified name inside the code.
You might also try javac -Xlint:-deprecation not sure if that would address it.
I solved this by changing the import to:
import package.*
then annotating the method that used the deprecated classes with#SuppressWarnings("deprecation")
Suppose that you are overriding/implementing an interface with a deprecated method (such as the getUnicodeStream(String columnLabel) in java.sql.ResultSet) then you will not get rid of deprecation warnings just by using the annotation #SuppressWarnings( "deprecation" ), unless you also annotate the same new method with the #Deprecated annotation. This is logical, because otherwise you could undeprecate a method by just overriding its interface description.
you can use:
javac FileName.java -Xlint:-deprecation
But then this will give you warnings and also tell you the part of the code that is causing deprecation or using deprecated API. Now either you can run your code with these warnings or make appropriate changes in the code.
In my case I was using someListItem.addItem("red color") whereas the compiler wanted me to use someListItem.add("red color");.
If #SuppressWarnings("deprecation") is not working for you like for me. You can find exact squid number in sonar lint plugin. And then you can simply suppress warning: #SuppressWarnings("squid:CallToDeprecatedMethod")

Categories

Resources