Quarkus UnsatisfiedResolutionException for Mapstruct - dependency-injection

I am trying to use Mapstruct in my Quarkus project, but when i run the app with /.mvnw compile quarkus:dev
i got the following exception:
javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type
org.acme.dto.mapper.BookMapper and qualifiers [#Default]
(I have checked the generated classes in target/generated-sources, and they get #ApplicationScoped)
Details:
Mapstruct dependencies are added to the pom.xml as:
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
<scope>provided</scope>
</dependency>
Than i have several mappers like:
#Mapper(componentModel = "cdi", uses = { BookDetailsMapper.class, AuthorMapper.class })
public interface BookMapper {
BookDto toDto(Book book);
Book toEntity(BookDto bookDto);
}
#Mapper(componentModel = "cdi")
public interface AuthorMapper {
AuthorDto toDto(Author author);
Author toEntity(AuthorDto author);
}
#Mapper(componentModel = "cdi")
public interface BookDetailsMapper {
BookDetailsDto toDto(BookDetails bookDetails);
BookDetails toEntity(BookDetailsDto bookDetailsDto);
}
And the BookMapper bean is injected in:
#ApplicationScoped
public class BookService {
private final BookMapper bookMapper;
#Inject
public BookService(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}
...

The problem was that generated-sources of mapstruct was not compiled to class files.
I had to add the mapstruct-processor dependency as follows:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.platform.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>

Related

UserTypeResolver must not be null

I have been attempting to test out an insert of a Cassandra UDT, and i keep running into the following error:
Exception in thread "main" java.lang.IllegalArgumentException: UserTypeResolver must not be null
After just trying to figure my own way through it, i attempted to exactly replicate the approach outlined in the following:
User Defined Type with spring-data-cassandra
However, i still get the same error.
I am able to insert to the target DB when i remove the UDT and just insert the simple types, so I know that I am connecting appropriately. My config is as follows:
#Configuration
#PropertySource(value = { "classpath:cassandra.properties" })
//#EnableCassandraRepositories(basePackages = { "org.spring.cassandra.example.repo" })
public class CassandraConfig {
private static final Logger LOG = LoggerFactory.getLogger(CassandraConfig.class);
#Autowired
private Environment env;
#Bean
public CassandraClusterFactoryBean cluster() {
CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
cluster.setContactPoints(env.getProperty("cassandra.contactpoints"));
cluster.setPort(Integer.parseInt(env.getProperty("cassandra.port")));
return cluster;
}
#Bean
public CassandraMappingContext mappingContext() {
BasicCassandraMappingContext mappingContext = new BasicCassandraMappingContext();
mappingContext.setUserTypeResolver(new SimpleUserTypeResolver(cluster().getObject(), "campaign_management"));
return mappingContext;
}
#Bean
public CassandraConverter converter() {
return new MappingCassandraConverter(mappingContext());
}
#Bean
public CassandraSessionFactoryBean session() throws Exception {
CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();
session.setCluster(cluster().getObject());
session.setKeyspaceName(env.getProperty("cassandra.keyspace"));
session.setConverter(converter());
session.setSchemaAction(SchemaAction.NONE);
return session;
}
#Bean
public CassandraOperations cassandraTemplate() throws Exception {
return new CassandraTemplate(session().getObject());
}
}
My Address and Employee classes are exactly as shown in the SO question i reference above, and my Main is simply:
public class MainClass {
public static void main(String[] args) {
ApplicationContext service = new AnnotationConfigApplicationContext(CassandraConfig.class);
Employee employee = new Employee();
employee.setEmployee_id(UUID.randomUUID());
employee.setEmployee_name("Todd");
Address address = new Address();
address.setAddress_type("Home");
address.setId("ToddId");
employee.setAddress(address);
CassandraOperations operations = service.getBean("cassandraTemplate", CassandraOperations.class);
operations.insert(employee);
System.out.println("Done");
}
}
I am using:
datastax.cassandra.driver.version=3.1.3
spring.data.cassandra.version=1.5.1
spring.data.commons.version=1.13.1
spring.cql.version=1.5.1
The version referenced in the previous SO question is 1.5.0, though spring.io lists 1.5.1 as current, so I am using that, and no 1.5.0 is shown available.
Any help would be appreciated, as this is driving me somewhat nuts.
You typically get this error when you miss a UserTypeResolver under your cassandra Mapping, itself used by the cassandra Converter, itself used by the Spring Data Cassandra Template
For the details:
Assuming you have a basic Spring MVC Controller up and running elsewhere...
UserDefinedTypes in Cassandra being most interesting within SETs and MAPs, the example below is of such kind.
Example Spring Bean configuration with all defaults (Spring XML application context extract):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cassandra="http://www.springframework.org/schema/data/cassandra"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/data/cassandra http://www.springframework.org/schema/data/cassandra/spring-cassandra.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
...
<!-- ===== CASSANDRA ===== -->
<!-- Loads the properties into the Spring Context and uses them to fill in placeholders in bean definitions below -->
<context:property-placeholder location="/WEB-INF/spring/cassandra.properties" />
<!-- REQUIRED: The Cassandra Cluster -->
<cassandra:cluster contact-points="${cassandra.contactpoints}"
port="${cassandra.port}" username="cassandra" password="cassandra"
auth-info-provider-ref="authProvider" />
<!-- REQUIRED: The Cassandra Session, built from the Cluster, and attaching to a keyspace -->
<cassandra:session keyspace-name="${cassandra.keyspace}" />
<!-- REQUIRED: The Default Cassandra Mapping Context used by CassandraConverter
DO include a userTypeResolver for UDT support -->
<cassandra:mapping entity-base-packages="fr.woobe.model">
<cassandra:user-type-resolver keyspace-name="${cassandra.keyspace}" />
</cassandra:mapping>
<!-- REQUIRED: The Default Cassandra Converter used by CassandraTemplate -->
<cassandra:converter />
<bean id="authProvider" class="com.datastax.driver.core.PlainTextAuthProvider">
<constructor-arg index="0" value="myCassandraUser" />
<constructor-arg index="1" value="somePassword" />
</bean>
<!-- REQUIRED: The Cassandra Template is the building block of all Spring Data Cassandra -->
<cassandra:template id="cassandraTemplate" />
...
and then in java, typically within your Spring MVC controller:
import org.springframework.data.cassandra.core.CassandraOperations;
...
// acquire DB template
CassandraOperations cOps = this.beanFactory.getBean("cassandraTemplate", CassandraOperations.class);
// for instance: load everything
List<MyData> rows = cOps.select("SELECT * FROM mydatatable", MyData.class);
// assuming an entry with index i exists...
Set<Pair> mySetOfPairs = rows.get(i).pairSet;
if (mySetOfPairs!=null)
for (Pair p : mySetOfPairs) {
... handle p.first and p.second ...
...
with this kind of entity mappings:
package example.model;
import java.util.Set;
import org.springframework.data.cassandra.core.mapping.CassandraType;
import org.springframework.data.cassandra.core.mapping.PrimaryKey;
import org.springframework.data.cassandra.core.mapping.Table;
import com.datastax.driver.core.DataType.Name;
#Table public class MyData {
#PrimaryKey
public String myKey;
// some other basic fields...
public String moreStuff;
// a SET of user defined 'pair type'
#CassandraType(type = Name.SET, userTypeName = "pairType")
public Set<Pair> pairSet;
// your constructors and other methods here...
}
and a user defined entity like:
package example.model;
import org.springframework.data.cassandra.core.mapping.UserDefinedType;
#UserDefinedType("pairType")
public class Pair {
public String first;
public String second;
public Pair() {
}
public Pair(String f, String s) {
this.first= f;
this.second= s;
}
}
all based on a Cassandra table created as:
CREATE TYPE pairType (first text, second text);
CREATE TABLE MyData (
myKey text,
moreStuff text,
pairSet set<frozen<pairType>>,
PRIMARY KEY (myKey)
) ;
INSERT INTO MyData (myKey, moreStuff, pairSet)
VALUES ('hello', 'world', {
{ first:'one', second:'two' },
{ first:'out', second:'there' } }
) ;
In term of Maven artifacts or libraries, spring-webmvc is indeed required if you run within a Web MVC Spring Controller, and then spring-context-support, and spring-data-cassandra. The DataStax cassandra driver comes along as a dependency.

Compute property arithmetically

In short I am not able to make a computation based on a property within my build file.
Let's say I have:
<property name="basedir" value="${project.basedir}" /> <--Current value 73
How can I know the previous 3 builds (72,71 and 70) OR how can I compute these values(based on the basedir property)?
I have tried (ignore the addition):
<property name="basedir" value="${project.basedir}+1" /> <--But it concats the value: 73+1
<property name="basedir" value="${project.basedir+1}" /> <--But it is just wrong: build_${env.BUILD_NUMBER+1}
Scenario: Remove old releases (keep some releases in case of a rollback)
P.S: The duplicate link is invalid because this is a deployment via PHING not ANT
You could use an adhoc-task for this:
<?xml version="1.0"?>
<project default="main" phingVersion="2.11.0">
<property name="basedir" value = "73"/>
<adhoc-task name="increment"><![CDATA[
class increment extends Task {
private $value;
function setvalue($value) {
$this->value = $value;
}
function setProperty($property) {
$this->property = $property;
}
function main() {
$this->project->setProperty($this->property, ((int) $this->value + 1));
}
}
]]></adhoc-task>
<target name="main">
<echo>${basedir}</echo>
<increment value="${basedir}" property="basedir"/>
<echo>${basedir}</echo>
</target>
</project>

Howto inject Plexus component into Mojo

Is it possible to inject a Plexus component into a Mojo.
Here's what I tried but myComponent is always null.
My Component:
import org.codehaus.plexus.component.annotations.Component;
#Component(role = MyComponent.class, hint = "mine")
public class MyComponent {
}
My Mojo:
import org.codehaus.plexus.component.annotations.Requirement;
import org.apache.maven.plugins.annotations.Component;
public class MyMojo extends AbstractMojo {
#Requirement(role = MyComponent.class, hint = "mine", optional = false)
protected MyComponent myComponent;
#Component
protected MavenProject project;
}
You Java part is correct, but you need to add some sources processing to build of your Maven plugin. This can be achieved by adding the following to your build in pom.xml:
<plugin>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-metadata</artifactId>
<version>2.0.0</version>
<executions>
<execution>
<id>process-classes</id>
<goals>
<goal>generate-metadata</goal>
</goals>
</execution>
</executions>
</plugin>

accessing ant properties in groovy taskdef gives Null Pointer Exception

I am trying to execute following code but I am getting null pointer exception.
<property name="from" value="from"/>
<property name="to" value="to"/>
<taskdef name="groovy"
classname="org.codehaus.groovy.ant.Groovy"
classpath="G:\Tibco_Training\groovy-binary-1.8.5\groovy-all-1.6.5.jar" />
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<groovy>
class MoveDir extends org.apache.tools.ant.Task {
//def from = 'from'
//def to = 'to'
public void execute() {
new File(properties.from).eachFileMatch ~/.*/, { file ->
file.renameTo(new File(properties.to , file.getName()))
println "Moving file: $file.name from: " + from + " to: " + to }
}
}
project.addTaskDefinition('movedir', MoveDir)
</groovy>
<movedir />
If I don't use ant properties in groovy then the code works fine, but when I use ant properties for specifying directories, then it give null pointer exception. Am I passing wrong values or wrong syntax is the cause.
Wrong syntax, you have to use properties.'to' and properties.'from'

ant not executing .exe file

my searchversion.exe file is not running in the script..why is that so?
<project name="nightly_build" default="main" basedir="checkout">
<target name="init">
<property file="initial.properties"/>
<property file="C:/Work/lastestbuild.properties"/>
<tstamp>
<format property="suffix" pattern="yyyyMMddHHmmss"/>
</tstamp>
</target>
<target name="main" depends="init">
<sequential>
<exec executable="C:/Work/Searchversion.exe"/>
...
</sequential>
</target>
</project>
Searchversion.exe will generate latestbuild.properties file. I do not have any arguments for Searchversion.exe.
Here is the code for searchversion.exe:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Search
{
class Program
{
static void Main(string[] args)
{
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "sslist.exe";
p.StartInfo.Arguments = "-R -H -h sinsscm01.ds.net /mobile";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.Start();
string procOutput = p.StandardOutput.ReadToEnd();
string procError = p.StandardError.ReadToEnd();
TextWriter outputlog = new StreamWriter("C:\\Work\\listofsnapshot.txt");
outputlog.Write(procOutput);
outputlog.Close();
string greatestVersionNumber = "";
using (StreamReader sr = new StreamReader("C:\\Work\\listofsnapshot.txt"))
{
while (sr.Peek() >= 0)
{
var line = sr.ReadLine();
var versionNumber = line.Replace(#"6.70_Extensions/6.70.102/ANT_SASE_RELEASE_", "");
if(versionNumber.Length != line.Length)
greatestVersionNumber = versionNumber;
}
}
Console.WriteLine(greatestVersionNumber);
TextWriter latest = new StreamWriter("C:\\Work\\latestbuild.properties");
latest.Write("Version_Number=" + greatestVersionNumber);
latest.Close();
}
}
}
sslist.exe gets a list of snapshots found in my version control software, and i will get the greatest version number and save it as a text (latestbuild.properties)
Two things in your script look odd.
I don't think you need the <sequential> task in the <main> target.
The depends attribute of you <main> target will cause the <init> target to run before Searchversion.exe. So, perhaps it is getting run, just too late.
Assuming #2 is the cause of your problem you should restructure your script to look like this:
<project name="nightly_build" default="main" basedir="checkout">
<target name="init">
<exec executable="C:/Work/Searchversion.exe"/>
<property file="initial.properties"/>
<property file="C:/Work/lastestbuild.properties"/>
<tstamp>
<format property="suffix" pattern="yyyyMMddHHmmss"/>
</tstamp>
</target>
<target name="main" depends="init">
...
</target>
</project>

Resources