Previous, I am building my app using
def room_version = '2.5.0'
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
Today, when I remove
annotationProcessor "androidx.room:room-compiler:$room_version"
The app is still fully build-able. My app does use @Dao
, @Entity
, ...
May I know, why is it so? I thought the reason we are using annotationProcessor
, because we want to support @Dao
, @Entity
, ...?
The Room compiler annotation processor generates java code from the respective annotations (descried below). The generated code is only then invoked at run time. Hence the lack of the code does not result in a compile time issue (but a run time issue/exception).
Primarily it generates code for each @Database
annotated class and for each @Dao
annotated interface or abstract class.
The generated code is placed in the java (generated)
folder (visible from the Android
view of the project explorer).
for each @Database
abstract class there will be a class that is the same name as the @Database
annotated class but suffixed with _Impl
.
entities
parameter of the @Database
annotation that defines the @Entity
annotated classes that are then deemed to be the tables that Room will use.for each @Dao
annotated abstract class or interface (typically the latter) there will be a a class that is the same name as the @Dao
annotated class/interface but suffixed with _Impl
Without the annotation processer for the compiler (aka removing the line), then there will be no complaint to compile time as effectively you are saying that you are not using Room.
However, if you then try to run the App (if it attempts to use Room), you will then get a run time exception stating that the @Database
class suffixed with _Impl
does not exist, even though there is no compile time error.
Demonstration
A project consists of an abstract class TheDatabase
annotated with @Database
as per:-
@Database(entities = {ArtistOriginal.class,ArtistOther1.class,ArtistOther2.class, ArtistOther3.class},version = 1,exportSchema = false)
@Entity
annotated classes.Within the TheDatabase
is also the line:-
abstract AllDAOs getAllDAOs();
@Dao
annotated interface/abstract class (the latter in this demo)) it including:-
@Dao
abstract class AllDAOs {
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract long insert(ArtistOriginal artistOriginal);
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract long insert(ArtistOther1 artistOther1);
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract long insert(ArtistOther2 artistOther2);
}
If the build gradle (module) excludes the room compiler as per:-
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.room:room-runtime:2.6.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
/* annotationProcessor 'androidx.room:room-compiler:2.6.1' */
}
Activity Code for MainActivity is
:-
public class MainActivity extends AppCompatActivity {
TheDatabase db;
AllDAOs dao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = TheDatabase.getInstance(this);
dao = db.getAllDAOs();
SupportSQLiteDatabase sdb = db.getOpenHelper().getWritableDatabase();
/* Ignored as no result will be returned */
Cursor cursor = sdb.query("INSERT INTO ArtistOriginal (name) VALUES ('Candido_via_query');");
DatabaseUtils.dumpCursor(cursor);
cursor.close();
logDataInDatabase(sdb,"QRYINS");
/* artist_id will be generated (1??? for the first run) */
sdb.execSQL("INSERT INTO ArtistOriginal (name) VALUES('Candido_via_execsql');");
logDataInDatabase(sdb,"EXEINS");
/* In this case the artist_id is 0 as int cannot be null */
ArtistOriginal ao = new ArtistOriginal();
ao.Name = "Candidi_via_@Insert";
long aiid = dao.insert(ao);
logDataInDatabase(sdb,"DAOINS");
/* In this case the artist_id is 0 as int cannot be null */
ArtistOther1 ao1 = new ArtistOther1();
ao1.Name = "Candido_via_@Insert";
long ao1id = dao.insert(ao1);
/* In this case the artist_id member is null as it is an Integer Object */
ArtistOther2 ao2 = new ArtistOther2();
ao2.Name = "Candido_via_@Insert";
long ao2id = dao.insert(ao2);
Cursor csr = db.query("" +
"SELECT 'ArtistOriginal',* FROM ArtistOriginal " +
"UNION ALL SELECT 'ArtistOther1',* FROM ArtistOther1 " +
"UNION ALL SELECT 'ArtistOther2',* FROM ArtistOther2",
null
);
DatabaseUtils.dumpCursor(csr);
csr.close();
}
void logDataInDatabase(SupportSQLiteDatabase sdb,String tag_suffix) {
Log.d("CSRDUMP_" + tag_suffix,"Dumping Cursor");
Cursor csr = db.query("" +
"SELECT 'ArtistOriginal' AS t,* FROM ArtistOriginal " +
"UNION ALL SELECT 'ArtistOther1',* FROM ArtistOther1 " +
"UNION ALL SELECT 'ArtistOther2',* FROM ArtistOther2",
null);
DatabaseUtils.dumpCursor(csr);
csr.close();
}
}
Then there is no issue compiling the project:-
BUILD SUCCESSFUL in 3s
31 actionable tasks: 31 executed
The Android View shows:-
However if an attempt is made to run the App then:-
2024-03-18 09:54:04.872 30483-30483/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: a.a.so77759888javaroomsimpleextratable, PID: 30483
java.lang.RuntimeException: Unable to start activity ComponentInfo{a.a.so77759888javaroomsimpleextratable/a.a.so77759888javaroomsimpleextratable.MainActivity}: java.lang.RuntimeException: Cannot find implementation for a.a.so77759888javaroomsimpleextratable.TheDatabase. TheDatabase_Impl does not exist
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.RuntimeException: Cannot find implementation for a.a.so77759888javaroomsimpleextratable.TheDatabase. TheDatabase_Impl does not exist
at androidx.room.Room.getGeneratedImplementation(Room.kt:58)
at androidx.room.RoomDatabase$Builder.build(RoomDatabase.kt:1351)
at a.a.so77759888javaroomsimpleextratable.TheDatabase.getInstance(TheDatabase.java:19)
at a.a.so77759888javaroomsimpleextratable.MainActivity.onCreate(MainActivity.java:21)
TheDatabase_Impl
does not exist.Now with the Room compiler annotation processor
:-
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.room:room-runtime:2.6.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
annotationProcessor 'androidx.room:room-compiler:2.6.1'
}
The build works as per :-
BUILD SUCCESSFUL in 3s
31 actionable tasks: 11 executed, 20 up-to-date
Android View :-
If an attempt is made to run the App then:-
The app runs without an exception. The Log includes some expected output:-
2024-03-18 10:01:34.082 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@8c94956
2024-03-18 10:01:34.082 I/System.out: <<<<<
2024-03-18 10:01:34.082 D/CSRDUMP_QRYINS: Dumping Cursor
2024-03-18 10:01:34.084 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@8f4e6c4
2024-03-18 10:01:34.086 I/System.out: 0 {
2024-03-18 10:01:34.086 I/System.out: t=ArtistOriginal
2024-03-18 10:01:34.086 I/System.out: Artist_id=1
2024-03-18 10:01:34.086 I/System.out: Name=Candido_via_query
2024-03-18 10:01:34.086 I/System.out: }
2024-03-18 10:01:34.086 I/System.out: <<<<<
2024-03-18 10:01:34.087 D/CSRDUMP_EXEINS: Dumping Cursor
2024-03-18 10:01:34.087 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@e2e29ad
2024-03-18 10:01:34.088 I/System.out: 0 {
2024-03-18 10:01:34.088 I/System.out: t=ArtistOriginal
2024-03-18 10:01:34.088 I/System.out: Artist_id=1
2024-03-18 10:01:34.088 I/System.out: Name=Candido_via_query
....
App Inspection also confirms that the database exists and contains data e.g. :-
If the Room compiler annotation processor is removed, then again the code will compile but as the code is not generated (the old code being removed):-