Injecting another project in mojo - maven

I am trying to develop a mojo, where i am injecting my project in my plugin to list out all the dependencies defined in the project.
#Parameter(defaultValue = "${project}", required = true, readonly = true)
private MavenProject project;
Is it possible to inject another project ? For e.g. i have 1 project
A it has sub project X, Y and Z. When the plugin executed i would like the project Y also injected in my plugin, so that i can get dependencies from that project as well. I tried something like this.
#Parameter(defaultValue = "${project}", property = "other.project", required = true, readonly = true)
private MavenProject project2;
But doesnot seems to be working. project2 is always null.

Related

Kotlin & Spring (Data): custom setters

I currently am working on a project that uses Spring Boot, written in Kotlin. It has got to be mentioned that I am still relatively new to Kotlin, coming from Java. I have a small database consisting of a single table that is used to look up files. In this database, I store the path of the file (that for this testing purpose is simply stored in the the resources of the project).
The object in question looks as follows:
#Entity
#Table(name = "NOTE_FILE")
class NoteFile {
#Id
#GeneratedValue
#Column(name = "id")
var id: Int
#Column(name = "note")
#Enumerated(EnumType.STRING)
var note: Note
#Column(name = "instrument")
var instrument: String
#Column(name = "file_name")
var fileName: String
set(fileName) {
field = fileName
try {
file = ClassPathResource(fileName).file
} catch (ignored: Exception) {
}
}
#Transient
var file: File? = null
private set
constructor(id: Int, instrument: String, note: Note, fileName: String) {
this.id = id
this.instrument = instrument
this.note = note
this.fileName = fileName
}
}
I have created the following repository for retrieving this object from the database:
#Repository
interface NoteFileRepository : CrudRepository<NoteFile, Int>
And the following service:
#Service
class NoteFileService #Autowired constructor(private val noteFileRepository: NoteFileRepository) {
fun getNoteFile(id: Int): NoteFile? {
return noteFileRepository.findById(id).orElse(null)
}
}
The problem that I have is when I call the getNoteFile function, neither the constructor nor the setter of the constructed NoteFile object are called. As a result of this, the file field stays null, whereas I expect it to contain a value. A workaround this problem is to set the fileName field with the value of that field, but this looks weird and is bound to cause problems:
val noteFile: NoteFile? = noteFileService.getNoteFile(id)
noteFile.fileName = noteFile.fileName
This way, the setter is called and the file field gets the correct value. But this is not the way to go, as mentioned above. The cause here could be that with the Spring Data framework, a default constructor is necessary. I am using the necessary Maven plugins described here to get Kotlin and JPA to work together to begin with.
Is there some way that the constructor and/or the setter does get called when the object is constructed by the Spring (Data) / JPA framework? Or maybe should I explicitly call the setter of fileName in the service that retrieves the object? Or is the best course of action here to remove the file field as a whole and simply turn it into a function that fetches the file and returns it like that?

orphanRemoval causes error with lazy loaded collection

I use hibernate 5.0.8 and spring data jpa 1.10.1
Given these entities
class Model {
#ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
#JoinColumn(nullable = false)
private Configuration configuration;
//more fields and methods
}
class Configuration {
#OneToMany(mappedBy = "configuration", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Setting> settings = new ArrayList<>();
//more fields and methods
//settings is never assigned again - I use settings.add(...) and settings.clear()
}
class Setting {
#ManyToOne
#JoinColumn(nullable = false)
private Configuration configuration;
//more fields and methods
}
Model is the master, but multiple models can use the same configuration. The cascading on configuration in Model is required, because if I change anything in the Configuration, I want it to be applied in all Models using this Configuration
Now when I retrieve an existing Model with a Configuration that has settings, and save this Model, without applying any changes to the settings I get following exception
#Transactional
public void doSomething() {
Model model = modelRepository.findOne(0);
//change something in the model, but no changes are made in its configuration
//or do nothing
modelRepository.save(model);
}
I get the following exception
A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: Configuration.settings
I suspect this has something to do with the settings being lazy loaded and hibernate trying to merge an empty list into the configuration.
What am I doing wrong?
Check the getters and setters of the objects you are trying to clean up as orphans while dereferencing:
Try and use :
public void setChildren(Set<Child> aSet) {
//this.child= aSet; //Results in this issue
//change to
this.child.clear();
if (aSet != null) {
this.child.addAll(aSet);
} }
The problem was being caused by using enableLazyInitialization from the hibernate-enhance-maven-plugin. I still have no idea why it was causing this error, but removing this plugin resolved the issue.
I used this plugin, because I wanted to lazy load a large String field in Model that I would cache in the application. I will now change it to a OneToOne relation that is fetched lazily.

Sonar errors wehn using Lombok #Setter(value = AccessLevel.PRIVATE)

If I use the Lombok #Setting annotation on a field with a value of PRIVATE
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Notification implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Setter(value = AccessLevel.PRIVATE)
private String id;
private long userId;
private Event event;
private long timestamp = System.currentTimeMillis();
public Notification(final String id) {
this.id = id;
}
}
The Sonar Maven plugin gives the following error:
ERROR] Failed to execute goal org.codehaus.mojo:sonar-maven-plugin:2.7.1:sonar (default-cli) on project mio-events: Unable to analyze .class file tv/nativ/mio/event/model/Notification: 0 is not a valid line for a file -> [Help 1]
Changing the #Setting value to public fixes the issue, as does removing #Setting altogether and adding a manual private setter for the field.
Any idea what the issue might be?
Thanks
Nick
Sonar doesn't really support Lombok: Feature request for lombok like tools
Prior to running sonar you should delombok the source and use the generated sources for analysis. Information about this is on the page: Delombok. If you are using maven there's an example of using this technique here: Example Pom

maven plugin - get artifactId of plugin in Mojo

Is it possible to get the artifactId of the current Mojo?
#Mojo(...)
public class MyMojo extends AbstractMojo {
#Parameter(property = "project")
private MavenProject project;
#Parameter(property = "inputDirectory", defaultValue = "${project.basedir}/src/main/${artifact id of the plugin}")
private File inputDirectory;
...
I could hardcode the artifact id of the plugin, but I would rather get it dynamically.
The accepted answer does not answer the question.
You can use a field to dynamically get the artifactId of the mojo (not the artifactId of the project which the plugin is attached on)
#Parameter(defaultValue = "${mojo.artifactId}")
private String mojoArtifactId;
Or in your case:
#Parameter(property = "project")
private MavenProject project;
#Parameter(property = "inputDirectory", defaultValue = "${project.basedir}/src/main/${mojo.artifactId}")
private File inputDirectory;
BTW what comes into my mind is that you are using old style injection
#Parameter(property = "project")
private MavenProject project;
#Parameter(property = "inputDirectory", defaultValue = "${project.basedir}/src/main/${artifact id of the plugin}")
private File inputDirectory;
They should look like this:
The expression values for defaultValue are documented here:
http://maven.apache.org/ref/3.1.1/maven-core/apidocs/org/apache/maven/plugin/PluginParameterExpressionEvaluator.html depending on your used Maven version.
#Parameter(defaultValue = "${project}, required = true, readonly = true)
private MavenProject project;
#Parameter(defaultValue = "${project.basedir}/src/main/${artifact id of the plugin}", property = "inputDirectory", required = true)
private File inputDirectory;

Grails 3.x: Re-using JPA/Hibernate Domain classes: Domain class not found

I have a Spring 4.1.0 back-end application with domain classes annotated in JPA (w/Hibernate 4.3.5 as the persistence provider) using Maven as the build tool. I now want to add a web front-end component to this app and have decided to use Grails 3.x as my web framework. I want to re-use my existing JPA annotated domain classes with Grails and then use generate-all to create controllers and views for each domain model. My first milestone goal is to get basic CRUD functionality on the old domain models from this web app.
Following the information I found in the Grails documentation and in some older blog posts as well as some slightly related SO posts, I created a new Grails project and packaged up my existing project as a jar and installed it (I ran mvn install -DskipTests to be exact) and then added it to build.gradle (actually I just want to have one project in the end, but I thought I'd try it this way first because I don't want to wrestle with having Maven and Gradle in the same project yet):
repositories {
...
mavenLocal()
...
}
dependencies {
...
compile "com.my-company:my-spring-app:1.0.0.CI-SNAPSHOT"
...
}
No warnings or errors from IntelliJ IDEA 14 so far. Then I created the grails-app/conf/hibernate/hibernate.cfg.xml file and tried putting just one of my old JPA annotated entities in it for now:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<mapping package="com.my-company.my-spring-app.domain" />
<mapping class="com.my-company.my-spring-app.domain.City" />
</session-factory>
</hibernate-configuration>
No complaints from the IDE here either.
The City.java entity class looks something like:
package com.my-company.my-spring-app.domain;
import javax.persistence.*;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
/**
* City generated by hbm2java
*/
#Entity
#Table(name = "city",
schema = "public",
uniqueConstraints = #UniqueConstraint(columnNames = "name"))
public class City implements java.io.Serializable {
private static final long serialVersionUID = 4674557242772722625L;
#Id
#SequenceGenerator(name = "city_gen",
schema = "public",
sequenceName = "city_id_seq")
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "city_gen")
#Column(name = "id",
unique = true,
nullable = false)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "countryid",
nullable = false)
// #JoinColumn(name = "country_id", nullable = false)
private Country country;
#Column(name = "name",
unique = true,
length = 200)
private String name;
...
}
Then I jumped into the Grails console and tried to generate the controller and views for the City domain class:
grails generate-all com.my-company.my-spring-app.domain.City
But I just get a Domain class not found error:
| Error domain class not found for name com.my-company.my-spring-app.domain.City
I quickly created a Grails 2.5.0 app, put the my-spring-app.jar in lib/ and tried this again to see if it was an issue with the 'bleeding edge' Grails 3.0.1 but got the same result.
Does anyone know what's going on here? How can I re-use my old JPA domain classes with Grails 3.x so that I can stay DRY with only one set of domain entities?
I resolved a similar issue by putting hibernate.cfg.xml in grails-app/conf (not inside a hibernate subdirectory) as described in mapping-with-hibernate-annotations-in-grails-3-0-1.

Resources