I use a Room database class on Android Studio.
I have the following entities:
User, Address, Geo, Company, Album, Photo, AlbumPhotoCrossRef (there's many-to-many relationship between Album and Photo). And I added Word too just to test.
The code for these entities are added below.
When I use only Word (comment out other classes in the entities = part, it works, I can see the table via DatabaseInspector.
But when include all entities, the database don't even open, I can't even see name of the database on DatabaseInspector.
And I get the following error:
E/AndroidRuntime: FATAL EXCEPTION: pool-2-thread-1
Process: com.example.lab8_2_room_albums, PID: 8775
java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.
at androidx.room.RoomOpenHelper.checkIdentity(RoomOpenHelper.java:154)
at androidx.room.RoomOpenHelper.onOpen(RoomOpenHelper.java:135)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onOpen(FrameworkSQLiteOpenHelper.java:142)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:427)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:316)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:92)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:53)
at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:476)
at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:281)
at com.example.lab8_2_room_albums.dao.WordDao_Impl.insert(WordDao_Impl.java:57)
at com.example.lab8_2_room_albums.MainActivity.lambda$onCreate$0(MainActivity.java:59)
at com.example.lab8_2_room_albums.-$$Lambda$MainActivity$h9d6n2GFmqhE1uxj4ezb0-bRXOU.run(Unknown Source:2)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
I/Process: Sending signal. PID: 8775 SIG: 9
It refers to the line in the MainActivity where I run dao.insert(word) also where I insert a word. into database.
I did clean the project, rebuld the project too, but I still get the same error. Why? How to figure out what's wrong? And how can I fix this?
The database class is like below:
package com.example.lab8_2_room_albums.db;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.sqlite.db.SupportSQLiteDatabase;
import com.example.lab8_2_room_albums.dao.PhotoDAO;
import com.example.lab8_2_room_albums.dao.UserDAO;
import com.example.lab8_2_room_albums.dao.WordDao;
import com.example.lab8_2_room_albums.entities.Address;
import com.example.lab8_2_room_albums.entities.Album;
import com.example.lab8_2_room_albums.entities.AlbumPhotoCrossRef;
import com.example.lab8_2_room_albums.entities.Company;
import com.example.lab8_2_room_albums.entities.Geo;
import com.example.lab8_2_room_albums.entities.Photo;
import com.example.lab8_2_room_albums.entities.User;
import com.example.lab8_2_room_albums.entities.Word;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
#Database(entities = {Word.class, User.class, Address.class, Geo.class, Company.class, Album.class, Photo.class, AlbumPhotoCrossRef.class}, version = 1, exportSchema = true)
public abstract class UserRoomDatabase extends RoomDatabase {
//public abstract UserDAO userDAO();
// public abstract PhotoDAO photoDAO();
public abstract WordDao wordDao();
// volatile: har sammenheng med multithreading. Sikrer at alle trĂ¥der ser samme kopi av INSTANCE.
private static volatile UserRoomDatabase INSTANCE;
private static final int NUMBER_OF_THREADS = 4;
public static final ExecutorService databaseWriteExecutor =
Executors.newFixedThreadPool(NUMBER_OF_THREADS);
public static UserRoomDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (UserRoomDatabase.class) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
UserRoomDatabase.class, "mydaaatabase")
.addCallback(sRoomDatabaseCallback)
.build();
}
}
return INSTANCE;
}
private static RoomDatabase.Callback sRoomDatabaseCallback = new RoomDatabase.Callback() {
/**
* Called when the database is created for the first time.
* This is called after all the tables are created.
* #param db
*/
#Override
public void onCreate(#NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
// If you want to keep data through app restarts,
// comment out the following block
databaseWriteExecutor.execute(() -> {
// Populate the database in the background.
WordDao wordDao = INSTANCE.wordDao();
//wordDao.deleteAll();
wordDao.insert(new Word("asd"));
wordDao.insert(new Word("adsds"));
wordDao.getAlphabetizedWords();
});
}
#Override
public void onOpen(#NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
}
};
/*
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
#Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE user "
+ " ADD COLUMN birth_year INTEGER");
}
};*/
}
And here's the Main Activity:
package com.example.lab8_2_room_albums;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import androidx.room.Room;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Toast;
import com.example.lab8_2_room_albums.dao.PhotoDAO;
import com.example.lab8_2_room_albums.dao.UserDAO;
import com.example.lab8_2_room_albums.dao.WordDao;
import com.example.lab8_2_room_albums.databinding.ActivityMainBinding;
import com.example.lab8_2_room_albums.db.UserRoomDatabase;
import com.example.lab8_2_room_albums.entities.Address;
import com.example.lab8_2_room_albums.entities.Album;
import com.example.lab8_2_room_albums.entities.AlbumWithPhotos;
import com.example.lab8_2_room_albums.entities.Company;
import com.example.lab8_2_room_albums.entities.Geo;
import com.example.lab8_2_room_albums.entities.Photo;
import com.example.lab8_2_room_albums.entities.User;
import com.example.lab8_2_room_albums.entities.UserWithAlbums;
import com.example.lab8_2_room_albums.entities.UserWithCompanyWithAddressWithGeo;
import com.example.lab8_2_room_albums.entities.Word;
import com.example.lab8_2_room_albums.viewmodel.UserAlbumsViewModel;
public class MainActivity extends AppCompatActivity {
private UserAlbumsViewModel userAlbumsViewModel;
private ActivityMainBinding activityMainBinding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ViewBinding:
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
activityMainBinding = ActivityMainBinding.inflate(layoutInflater);
setContentView(activityMainBinding.getRoot());
// userAlbumsViewModel = new ViewModelProvider(this).get(UserAlbumsViewModel.class);
UserRoomDatabase db = UserRoomDatabase.getDatabase(this);
WordDao dao = db.wordDao();
UserRoomDatabase.databaseWriteExecutor.execute(() -> {
// Populate the database in the background.
// If you want to start with more words, just add them.
Word word = new Word("Helloooo");
dao.insert(word);
word = new Word("Woooorld");
dao.insert(word);
dao.getAlphabetizedWords();
});
}
}
I add some words into the words table in database. It works without any problem.
Word class:
package com.example.lab8_2_room_albums.entities;
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
#Entity(tableName = "word_table")
public class Word {
#PrimaryKey
#NonNull
#ColumnInfo(name = "word")
private String mWord;
public Word(#NonNull String word) {this.mWord = word;}
public String getWord(){return this.mWord;}
}
WordDAO:
package com.example.lab8_2_room_albums.dao;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import com.example.lab8_2_room_albums.entities.Word;
import java.util.List;
#Dao
public interface WordDao {
// allowing the insert of the same word multiple times by passing a
// conflict resolution strategy
#Insert(onConflict = OnConflictStrategy.IGNORE)
void insert(Word word);
#Query("DELETE FROM word_table")
void deleteAll();
#Query("SELECT * FROM word_table ORDER BY word ASC")
LiveData<List<Word>> getAlphabetizedWords();
}
User class:
package com.example.lab8_2_room_albums.entities;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.ForeignKey;
import androidx.room.PrimaryKey;
#Entity(foreignKeys = {
#ForeignKey(entity = Address.class, parentColumns = "addressId", childColumns = "fk_addressId", onDelete = ForeignKey.CASCADE),
#ForeignKey(entity = Company.class, parentColumns = "companyId", childColumns = "fk_companyId", onDelete = ForeignKey.CASCADE)
})
public class User {
#PrimaryKey(autoGenerate = true)
public long userId;
public String name;
public String username;
public String email;
public long fk_addressId;
public String phone;
public String website;
public long fk_companyId;
public User(#NonNull String name, #NonNull String username, #NonNull String email, long fk_addressId,
#NonNull String phone, #NonNull String website, long fk_companyId) {
this.name = name;
this.username = username;
this.email = email;
this.fk_addressId = fk_addressId;
this.phone = phone;
this.website = website;
this.fk_companyId = fk_companyId;
}
}
Address:
package com.example.lab8_2_room_albums.entities;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.ForeignKey;
import androidx.room.PrimaryKey;
#Entity(foreignKeys = {
#ForeignKey(entity = Geo.class, parentColumns = "geoId", childColumns = "fk_geoId", onDelete = ForeignKey.CASCADE)
})
public class Address {
#PrimaryKey(autoGenerate = true)
public long addressId;
public String street;
public String suite;
public String city;
public String zipCode;
public long fk_geoId;
public Address(#NonNull String street, #NonNull String suite, #NonNull String city,
#NonNull String zipCode, long fk_geoId) {
this.street = street;
this.suite = suite;
this.city = city;
this.zipCode = zipCode;
this.fk_geoId = fk_geoId;
}
}
Geo:
package com.example.lab8_2_room_albums.entities;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
#Entity
public class Geo {
#PrimaryKey(autoGenerate = true)
public long geoId;
public double lat;
public double lng;
public Geo(#NonNull double lat, #NonNull double lng) {
this.lat = lat;
this.lng = lng;
}
}
Company:
package com.example.lab8_2_room_albums.entities;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
#Entity
public class Company {
#PrimaryKey(autoGenerate = true)
public long companyId;
public String name;
public String catchPhrase;
public String bs;
public Company(#NonNull String name, #NonNull String catchPhrase, #NonNull String bs) {
this.name = name;
this.catchPhrase = catchPhrase;
this.bs = bs;
}
}
Album:
package com.example.lab8_2_room_albums.entities;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.ForeignKey;
import androidx.room.PrimaryKey;
#Entity(foreignKeys = {
#ForeignKey(entity = User.class, parentColumns="userId", childColumns = "fk_userId", onDelete = ForeignKey.CASCADE)
})
public class Album {
#PrimaryKey(autoGenerate = true)
public long albumId;
public long fk_userId;
public String title;
public Album(#NonNull String title, long fk_userId) {
this.title = title;
this.fk_userId = fk_userId;
}
}
Photo:
package com.example.lab8_2_room_albums.entities;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
#Entity
public class Photo {
#PrimaryKey(autoGenerate = true)
public long photoId;
public String title;
public String url;
public String thumbnailUrl;
public Photo(#NonNull String title, #NonNull String url, #NonNull String thumbnailUrl) {
this.title = title;
this.url = url;
this.thumbnailUrl = thumbnailUrl;
}
}
AlbumPhotoCrossRef:
package com.example.lab8_2_room_albums.entities;
import androidx.room.Entity;
import androidx.room.ForeignKey;
#Entity(primaryKeys = {"albumId", "photoId"},
foreignKeys = {
#ForeignKey(entity = Album.class, parentColumns="albumId", childColumns = "albumId", onDelete = ForeignKey.CASCADE),
#ForeignKey(entity = Photo.class, parentColumns="photoId", childColumns = "photoId", onDelete = ForeignKey.CASCADE)
}
)
public class AlbumPhotoCrossRef {
public long albumId;
public long photoId;
}
You've changed the schema (structure) without changing the version number. Room's integrity checking has detected the change and hence the exception.
As you have MIGRATION_1_2 you probably just need to change the version number from 1 to 2 as per :-
#Database(entities = {Word.class, User.class, Address.class, Geo.class, Company.class, Album.class, Photo.class, AlbumPhotoCrossRef.class}, version = 2, exportSchema = true
The message in the log basically says the above bar about having a migration available as per :-
java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.
However, looking at the migration it's altering the user table by adding a column. This doesn't appear to cover the changes you say you have made (added Word entity/table). You may wish to consider the alternative.
The alternative is to uninstall the App and rerun and the new schema will be applied (not any good if the App has been published as any data will be lost).
Room undertakes this checking by the use of a table called room_master_table this table stores an identity hash which is generated according to the schema that room builds/maintains from the code. Change the schema (code) and the hash changes. If the hash mismatches and the version number is not changed then the exception (or similar in the case of down grade)
I am trying to create a Minecraft plugin with a command that will set the world name into config.yml. Except I keep getting "Cannot make a static reference to the non-static method getConfig() from the type JavaPlugin" when I attempt to set the config. I have already searched around for several way to fix this but I have not understood have to implement other situations into mine.
Here is my code:
Main.java:
package me.Liam22840.MurderRun;
import org.bukkit.plugin.java.JavaPlugin;
import me.Liam22840.MurderRun.commands.HelpCommand;
import me.Liam22840.MurderRun.commands.SetmapCommand;
public class Main extends JavaPlugin {
#Override
public void onEnable(){
loadConfig();
new HelpCommand(this);
new SetmapCommand(this);
}
public void loadConfig(){
getConfig().options().copyDefaults(true);
saveConfig();
}
}
SetmapCommand.java:
package me.Liam22840.MurderRun.commands;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import Utils.Utils;
import me.Liam22840.MurderRun.Main;
import me.Liam22840.MurderRun.getConfig;
public class SetmapCommand implements CommandExecutor{
private int count;
public SetmapCommand(Main plugin){
plugin.getCommand("Setmap").setExecutor(this);
}
#Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player)){
sender.sendMessage("Only players can execute this command!");
return true;
}
Player p = (Player) sender;
Location b_loc = p.getLocation();
if(p.hasPermission("MurderRun.Setworld")){
Main.getConfig().set("Maps." + p.getName() + count + ".World", b_loc.getWorld().getName());
Main.saveConfig();
p.sendMessage(Utils.chat("&4Map Set"));
return true;
} else{
p.sendMessage("You do not have the required permissions to execute this command!");
}
return false;
}
}
You can't directly call the Main class, because it is not static. To call it, you should do this in your Setmap class and the constructor:
private Main plugin;
public SetmapCommand(Main plugin){
this.plugin = plugin;
plugin.getCommand("Setmap").setExecutor(this);
}
After you did this, you can use in your Setmap class:
plugin.saveConfig();
How to write a test class for a class containing public final static strings in salesforce?
I tried using system.assertequals
Doesnt seem to work properly.
#isTest
private class Test_TPET_Constants{
private static testMethod void test() {
//TPET_Constants inst= new TPET_Constants();
System.assertEquals(TPET_Constants.PICKLIST_COLLAB_SERVICE_SECURE_EMAIL,'Enterprise Secure Email');
System.assertEquals(TPET_Constants.DRAFT_STATUS, 'Draft');
System.assertEquals(TPET_Constants.ACTIVE_STATUS, 'Active');
System.assertEquals(TPET_Constants.INACTIVE_STATUS, 'Inactive');
System.assertEquals(TPET_Constants.SUBMITTED_STATUS, 'Submitted');
System.assertEquals(TPET_Constants.REJECTED_STATUS , 'Rejected');
System.assertEquals(TPET_Constants.PICKLIST_COLLAB_SERVICE , 'Collab Service');
System.assertEquals(TPET_Constants.PENDING_IMPLEMENTATION_STATUS ,'Pending Implementation');
}
}
In your class you need to markthe variable #TestVisible. Check here: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation_testvisible.htm.
#TestVisible private static Integer recordNumber = 1;
Before I setup a test class like the code below:
1. the Factory and test Dataprovider both used excel as the dataprovider.
2. In the Factory dataprovider table, it has a list of url
3. Each time, it will find one of the url in the factory dataprovider table, and run the test in each test methods..
public class Test {
WebDriver driver;
private String hostName;
private String url;
#Factory(dataProvider = "xxxx global variables", dataProviderClass = xxxx.class)
public GetVariables(String hostName, String url) {
this.hostName = hostName;
this.url = url;
}
#BeforeMethod
#Parameters("browser")
public void start(String browser) throws Exception {
driver = new FirefoxDriver();
driver.get(url);
Thread.sleep(1000);
}
#Test(priority = 10, dataProvider = "dataprovider Test A", dataProviderClass = xxx.class)
public void TestA(Variable1,
Variable2,Variable3) throws Exception {
some test here...
}
#Test(priority = 20, dataProvider = "dataprovider Test B", dataProviderClass = xxx.class)
public void TestB(Variable1,
Variable2,Variable3)
throws Exception {
some test here...
}
#AfterMethod
public void tearDown() {
driver.quit();
}
Now I want to dynamically assign different group for each test for different url. I am thinking add a variable 'flag' in the #Factory dataprovider:
#Factory(dataProvider = "xxxx global variables", dataProviderClass = xxxx.class)
public GetVariables(String hostName, String url, String flag) {
this.hostName = hostName;
this.url = url;
this.flag = flag;
}
That when flag.equals("A"), it will only run test cases in test groups={"A"}.
When flag.equals("B"), it will only run test cases in test groups ={"B"},
When flag.equals("A,B"), it will only run test cases in test groups ={"A","B"}
Is there any way I can do that?
Thank you!
TestNG groups provides "flexibility in how you partition your tests" but it isn't for conditional test sets. For that you simply use plain old Java.
You can use inheritance or composition (I recommend the latter, see Item 16: Favor composition over inheritance from Effective Java).
Either way the general idea is the same: use a Factory to create your test class instances dynamically creating the appropriate class type with the appropriate test annotations and/or methods that you want to run.
Examples:
Inheritance
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
public class DemoTest {
#Factory
public static Object[] createTests() {
return new Object[]{
new FlavorATest(),
new FlavorBTest(),
new FlavorABTest()
};
}
/**
* Base test class with code for both A-tests and B-tests.
*
* Note that none of these test methods are annotated as tests so that
* subclasses may pick which ones to annotate.
*/
public static abstract class BaseTest {
protected void testA() {
// test something specific to flavor A
}
protected void testB() {
// test something specific to flavor B
}
}
// extend base but only annotate A-tests
public static class FlavorATest extends BaseTest {
#Test
#Override
public void testA() {
super.testA();
}
}
// extend base but only annotate B-tests
public static class FlavorBTest extends BaseTest {
#Test
#Override
public void testB() {
super.testB();
}
}
// extend base and annotate both A-tests and B-tests
public static class FlavorABTest extends BaseTest {
#Test
#Override
public void testA() {
super.testA();
}
#Test
#Override
public void testB() {
super.testB();
}
}
}
Composition
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
public class DemoTest {
#Factory
public static Object[] createTests() {
return new Object[]{
new FlavorATest(),
new FlavorBTest(),
new FlavorABTest()
};
}
private static void testA() {
// test something specific to flavor A
}
private static void testB() {
// test something specific to flavor B
}
// only create A-test methods and delegate to shared code above
public static class FlavorATest {
#Test
public void testA() {
DemoTest.testA();
}
}
// only create B-test methods and delegate to shared code above
public static class FlavorBTest {
#Test
public void testB() {
DemoTest.testB();
}
}
// create A-test and B-test methods and delegate to shared code above
public static class FlavorABTest {
#Test
public void testA() {
DemoTest.testA();
}
#Test
public void testB() {
DemoTest.testB();
}
}
}
Your factory methods won't be as simple as you'll need to use your "flag" from your test data to switch off of and create instances of the appropriate test classes.
I stuck at point i have one website for example (http://newtours.demoaut.com/) and for that i have created multiple classes likes:
App_Login(),
App_Dashboard(),
App_FliReservation(),
Cancel_Flight();
So want to call above all classes into single class .
can someone guide me on these.
Script sample
App_Login() class
public class App_login {
public static void main(String[] args) {
// TODO Auto-generated method stub
WebDriver driver= new FirefoxDriver();
driver.get("http://newtours.demoaut.com/");
}
}
and i want to call above class into following class
public class Mercurywebapp {
#Test
public void supp_onboarding() throws Exception {
App_Login();
}
public void App_Login() {
// TODO Auto-generated method stub
}
}
when i run above class (i.e.Mercurywebapp) then getting blank screen
Create another instances of all the Classes in the MercuryWebapp
Depends on the access modifiers for the classes
e.g
App_Login testObject = new App_Login();