error: incompatible types: SupportSQLiteDatabase cannot be converted to AppDatabase - android-room

I am trying to include Room persistence library to my android project. I am using gradle dependency android.arch.persistence.room:runtime:1.1.1 library, not the androidx
I have tried changing the version to 1.1.0 & 1.1.0-beta2 but getting same error.
Gradle dependencies for Room:
// Room components
implementation "android.arch.persistence.room:runtime:$rootProject.roomVersion"
annotationProcessor "android.arch.persistence.room:compiler:$rootProject.roomVersion"
androidTestImplementation "android.arch.persistence.room:testing:$rootProject.roomVersion"
Here $rootProject.roomVersion value is 1.1.1
Support library version:
`implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:support-v4:28.0.0'`
The AppDatabase class:
import android.arch.persistence.room.Database;
import android.arch.persistence.room.Room;
import android.arch.persistence.room.RoomDatabase;
import android.content.Context;
import com.samcaraschools.userlistapp.module.User;
#Database(entities = {User.class},version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public static AppDatabase mDatabase;
public abstract UserDao userDao();
public static AppDatabase getAppDatabase(Context context) {
if (mDatabase == null) {
synchronized (AppDatabase.class) {
if (mDatabase == null) {
mDatabase = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, "word_database")
// Wipes and rebuilds instead of migrating
// if no Migration object.
// Migration is not part of this practical.
.fallbackToDestructiveMigration()
.build();
}
}
}
return mDatabase;
}
}
With the above code in place I am getting the following error:
error: incompatible types: SupportSQLiteDatabase cannot be converted to AppDatabase
What is wrong with my code?

The error is because of the name of the object of class AppDatabase. Rename it to any object name than mDatabase, then it will function properly.
If you check your AppDatabase_Impl.java, you will notice that mDatabase has error. This is because SupportSQLiteDatabase.java has object name mDatabase which gets override by the object name placed in AppDatabase.

Related

How can I use an externally created singleton to satisfly a dependency in Spring?

Let's say I have a configuration like this:
#Configuration
open class AppConfig {
#Bean
open fun mainWindow(stage: Stage): MainWindow {
return MainWindow(stage)
}
}
I also have a class where my app gets initialized. I'm using JavaFX, so I can't create the stage myself, instead it gets passed in to a function.
class MyApplication : Application()
{
override fun start(stage: Stage)
{
// I can't create the stage myself.
val ctx = AnnotationConfigApplicationContext(AppConfig::class.java)
ctx.beanFactory.registerSingleton("stage", stage)
stage.run {
scene = Scene(mainWindow, 800.0, 600.0)
show()
}
}
}
I get an error in the configuration class that "Could not autowire. No beans of 'Stage' type found"
What can I do so that the stage I registered could be used to satisfy Stage dependencies?

IntelliJ UnitTests Kotlin and Java with same name

We have got a project from our university where they have created empty Java and Kotlin classes for us to add our code and some UnitTests to check if we have completed the assignments. I've been put in the Kotlin class and thus have to solve the problems in Kotlin and ignore Java. My problem now is that the UnitTests execute the Java code and not Kotlin.
For example:
Java Class:
package string;
public class Arrow {
public static String arrow(int length, boolean doubleEnded, boolean doubleLine) {
// TODO Implement the method
return "java";
}
}
Kotlin Class:
#file:JvmName("Arrow")
package string
// TODO Implement the function
fun arrow(length: Int, doubleEnded: Boolean, doubleLine: Boolean): String{
return "kotlin";
}
UnitTest and Result:
package string;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class ArrowTest {
static final int NBR_TESTS = 20;
#Test
void arrow0() {
Assertions.assertEquals("", Arrow.arrow(0, true, true));
Assertions.assertEquals("", Arrow.arrow(0, false, true));
Assertions.assertEquals("", Arrow.arrow(0, true, false));
Assertions.assertEquals("", Arrow.arrow(0, false, false));
}
}
org.opentest4j.AssertionFailedError:
Expected :
Actual :java
What do I have to do so that the UnitTests execute the Kotlin code and not Java?
They told us we should not change anything in the tests.
As #user3159253 commented changing the sourceDirectory did it for me.
I opened the module settings and removed Java as a source and added Kotlin.

Add dependence of the project into my custom gradle plugin

I'm new in the Gradle world and I'm writing a personal plugin for executing the operation on the database, an example:
create a database, delete the database, create a table e insert a value into database, but I have a problem with import dependence for the project that uses my plugin, an example for creating a database using a JDBC I have to need the driver JDBC for the database, this driver is content into project main.
My question is: How getting a dependency jar for the database into my Gradle plugin?
This is my code
package io.vincentpalazzo.gradledatabase.task;
import io.vincentpalazzo.gradledatabase.exstension.GradleDatabaseExstension;
import io.vincentpalazzo.gradledatabase.persistence.DataSurce;
import org.gradle.api.DefaultTask;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.tasks.TaskAction;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Iterator;
import java.io.File;
import java.util.Set;
/**
* #author https://github.com/vincenzopalazzo
*/
public class CreateDatabaseTask extends DefaultTask {
#TaskAction
public void createAction() {
GradleDatabaseExstension project = getProject().getExtensions().findByType(GradleDatabaseExstension.class);
String url = project.getUrl();
String driverClass = project.getDriver(); //The drive name database is different
String username = project.getUsername();
String password = project.getPassword();
String nameDatabase = project.getNameDatabase();
String nameJar = project.getNameJar();
if (findDependecyFileJarForDriver(nameJar)) {
System.out.println("Jar findend");
} else {
System.out.println("Jar not found");
}
DataSurce dataSource = new DataSurce();
if (dataSource.connectionDatabase(driverClass, url, username, password)) {
if (dataSource.createDatabese(nameDatabase)) {
System.out.println("Database " + nameDatabase + " created");
}
}
}
private boolean findDependecyFileJarForDriver(String nameJar) {
if (nameJar == null || nameJar.isEmpty()) {
throw new IllegalArgumentException("The input parameter is null");
}
Iterator<Configuration> iterable = getProject().getConfigurations().iterator();
boolean finded = false;
while ((!finded) || (iterable.hasNext())) {
Configuration configuration = iterable.next();
Set<File> filesSet = configuration.resolve();
for (File file : filesSet) {
String nameFile = file.getName();
if (nameFile.contains(nameJar)) {
//Now?;
finded = true;
}
}
}
return finded;
}
}
And this is my project and this is the referend for my post on Gradle forum
Sorry for my terrible English but I'm learning
I want to add the answer to this post.
The better solution I found is using this plugin
I used the plugin inside the my code, this is an example
public abstract class AbstractTaskGradleDatabase extends DefaultTask {
protected JarHelper jarHelper;
protected Optional<File> jar;
protected void init(){
jarHelper = new JarHelper(getProject());
jar = jarHelper.fetch("nameDependence");
}
}
inside the builld.gradle
dependencies {
implementation gradleApi()
implementation 'com.lingocoder:jarexec.plugin:0.3'
}
ps: the answer can be changed in the time because the version of the plugin is an beta

Why Spring #Service methods appear with 0% code coverage in JaCoCo?

These libraries are loaded:
JUnit 5.3.2
JaCoCo 0.8.2
Mockito 2.10.0
Only element "static {...}" appears with 100% coverage. All the rest is at 0%:
The unit test class has annotations #ExtendWith(SpringExtension.class) and #AutoConfigureMockMvc. The service is injected with #Mock.
doReturn(actual).when(service).get(param);
when(service.get(param)).thenReturn(actual);
expected = service.get(param);
verify(service, times(1)).get(param);
assertEquals(expected, actual);
assertEquals(actual, expected);
My ServiceImpl class is red when I click any method. It extends an abstract class. Jackson's ObjectMapper is red, and also the entire lines within the methods. For example:
public CustomReturnObject get(final CustomParamObject paramObject) {
try {
return retryTemplate.execute(status -> {
String json = repository.get(paramObject);
CustomReturnObject returnObject = json2CustomObject(json, paramObject);
if (returnObject == null) {
returnObject = new CustomReturnObject();
returnObject.setId(paramObject.getId());
}
return returnObject;
});
} catch (Exception ex) {
log.error(ex.getMessage(), ex);
return null;
}
}
Similarly to https://stackoverflow.com/a/46614216/244993 let's put aside Spring, because there is IMO clearly something wrong with your expectations/understanding about core thing here - mocking.
By
doReturn(actual).when(service).get(param);
expected = service.get(param);
verify(service, times(1)).get(param);
assertEquals(expected, actual);
you are not testing get method, you are testing something that always returns actual, no matter what is actually written in get, because in this case it is not executed.
Here is complete example as a proof:
src/main/java/hello/GreetingService.java:
package hello;
class GreetingService {
Object get(Object param) {
throw new UnsupportedOperationException();
}
}
src/test/java/hello/GreetingServiceTest.java:
package hello;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
#ExtendWith(MockitoExtension.class)
public class GreetingServiceTest {
#Mock
public GreetingService service;
#Test
void test() {
Object param = new Object();
Object actual = new Object();
doReturn(actual).when(service).get(param);
Object expected = service.get(param);
verify(service, Mockito.times(1)).get(param);
assertEquals(expected, actual);
}
}
build.gradle :
apply plugin: 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile 'org.mockito:mockito-junit-jupiter:2.23.4'
}
Real method get throws UnsupportedOperationException, however above test succeeds, so real method was not executed. As another way to proof that get not executed: put a breakpoint into it and execute test in debug mode from IDE - breakpoint won't be reached.
Coverage shows what was really executed and hence absolutely correct that it is zero for methods that are not executed.

JAXBElement: providing codec (/converter?) for class java.lang.Class

I have been evaluating to adopt spring-data-mongodb for a project. In summary, my aim is:
Using existing XML schema files to generate Java classes.
This is achieved using JAXB xjc
The root class is TSDProductDataType and is further modeled as below:
The thing to note here is that ExtensionType contains protected List<Object> any; allowing it to store Objects of any class. In my case, it is amongst the classes named TSDModule_Name_HereModuleType and can be browsed here
Use spring-data-mongodb as persistence store
This is achieved using a simple ProductDataRepository
#RepositoryRestResource(collectionResourceRel = "product", path = "product")
public interface ProductDataRepository extends MongoRepository<TSDProductDataType, String> {
TSDProductDataType queryByGtin(#Param("gtin") String gtin);
}
The unmarshalled TSDProductDataType, however, contains JAXBElement which spring-data-mongodb doesn't seem to handle by itself and throws a CodecConfigurationException org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class java.lang.Class.
Here is the faulty statement:
TSDProductDataType tsdProductDataType = jaxbElement.getValue();
repository.save(tsdProductDataType);
I tried playing around with Converters for spring-data-mongodb as explained here, however, it seems I am missing something since the exception is about "Codecs" and not "Converters".
Any help is appreciated.
EDIT:
Adding converters for JAXBElement
Note: Works with version 1.5.6.RELEASE of org.springframework.boot::spring-boot-starter-parent. With version 2.0.0.M3, hell breaks loose
It seems that I missed something while trying to add converter earlier. So, I added it like below for testing:
#Component
#ReadingConverter
public class JAXBElementReadConverter implements Converter<DBObject, JAXBElement> {
//#Autowired
//MongoConverter converter;
#Override
public JAXBElement convert(DBObject dbObject) {
Class declaredType, scope;
QName name = qNameFromString((String)dbObject.get("name"));
Object rawValue = dbObject.get("value");
try {
declaredType = Class.forName((String)dbObject.get("declaredType"));
} catch (ClassNotFoundException e) {
if (rawValue.getClass().isArray()) declaredType = List.class;
else declaredType = LinkedHashMap.class;
}
try {
scope = Class.forName((String) dbObject.get("scope"));
} catch (ClassNotFoundException e) {
scope = JAXBElement.GlobalScope.class;
}
//Object value = rawValue instanceof DBObject ? converter.read(declaredType, (DBObject) rawValue) : rawValue;
Object value = "TODO";
return new JAXBElement(name, declaredType, scope, value);
}
QName qNameFromString(String s) {
String[] parts = s.split("[{}]");
if (parts.length > 2) return new QName(parts[1], parts[2], parts[0]);
if (parts.length == 1) return new QName(parts[0]);
return new QName("undef");
}
}
#Component
#WritingConverter
public class JAXBElementWriteConverter implements Converter<JAXBElement, DBObject> {
//#Autowired
//MongoConverter converter;
#Override
public DBObject convert(JAXBElement jaxbElement) {
DBObject dbObject = new BasicDBObject();
dbObject.put("name", qNameToString(jaxbElement.getName()));
dbObject.put("declaredType", jaxbElement.getDeclaredType().getName());
dbObject.put("scope", jaxbElement.getScope().getCanonicalName());
//dbObject.put("value", converter.convertToMongoType(jaxbElement.getValue()));
dbObject.put("value", "TODO");
dbObject.put("_class", JAXBElement.class.getName());
return dbObject;
}
public String qNameToString(QName name) {
if (name.getNamespaceURI() == XMLConstants.NULL_NS_URI) return name.getLocalPart();
return name.getPrefix() + '{' + name.getNamespaceURI() + '}' + name.getLocalPart();
}
}
#SpringBootApplication
public class TsdApplication {
public static void main(String[] args) {
SpringApplication.run(TsdApplication.class, args);
}
#Bean
public CustomConversions customConversions() {
return new CustomConversions(Arrays.asList(
new JAXBElementReadConverter(),
new JAXBElementWriteConverter()
));
}
}
So far so good. However, how do I instantiate MongoConverter converter;?
MongoConverter is an interface so I guess I need an instantiable class adhering to this interface. Any suggestions?
I understand the desire for convenience in being able to just map an existing domain object to the database layer with no boilerplate, but even if you weren't having the JAXB class structure issue, I would still be recommending away from using it verbatim. Unless this is a simple one-off project, you almost definitely will hit a point where your domain models will need to change but your persisted data need to remain in an existing state. If you are just straight persisting the data, you have no mechanism to convert between a newer domain schema and an older persisted data scheme. Versioning of the persisted data scheme would be wise too.
The link you posted for writing the customer converters is one way to achieve this and fits in nicely with the Spring ecosystem. That method should also solve the issue you are experiencing (about the underlying messy JAXB data structure not converting cleanly).
Are you unable to get that method working? Ensure you are loading them into the Spring context with #Component plus auto-class scanning or manually via some Configuration class.
EDIT to address your EDIT:
Add the following to each of your converters:
private final MongoConverter converter;
public JAXBElement____Converter(MongoConverter converter) {
this.converter = converter;
}
Try changing your bean definition to:
#Bean
public CustomConversions customConversions(#Lazy MongoConverter converter) {
return new CustomConversions(Arrays.asList(
new JAXBElementReadConverter(converter),
new JAXBElementWriteConverter(converter)
));
}

Resources