Bukkit Persistance reimplemented - no code changes required!

Discussion in 'Plugin Development' started by LennardF1989, Jul 6, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    Jaker232

    Dang, I need to implement this!
     
  2. Offline

    troed

    Having read through all the posts in this thread, I assume this is still the way to go if thinking about adding Bukkit Persistence to a plugin? I can't really see any negatives, only positives.

    Comments from those of you who use it?
     
  3. Offline

    Acrobot

    Use it.

    :)

    It lets you turn off and on the default database, you can modify it by hand and only requires like 10 lines of code.
     
  4. What exactly does it support? (In terms of MySQL, SQLite, etc) I haven't really looked into it, so I can't say that I know myself. Or is ebean it's own storage?
     
  5. Offline

    Acrobot

    @tips48
    EBean is a persistence layer.
    It supports any type of database - you just need a connector (you can define its class and other settings in bukkit.yml)
     
  6. Alright, cool. Good to know!
     
  7. Offline

    AbdulAbdalla

    Does that plugin fix the random OptimisticLockExceptions too? I sometimes got them while working with mysql and having a float or double value in my entity class.

    I was able to delete a row and recreate it after that, but i was not allowed not update it without that annoying exception.
     
  8. Offline

    troed

    I just sat down and converted my project to Maven since that seemed to be the way the author prefers when using this library.

    However, am I right in assuming the maven repository for this project need to updated?

    Code:
    Could not find artifact org.bukkit:craftbukkit:jar:0.0.1-SNAPSHOT in lennardf1989-repo (http://github.lennardf1989.com/repository/
    It seems to reference both the old Bukkit repo paths and also the 0.0.1 naming not having been used for a while. Since LennardF1989 was last seen Sep 29, 2011 according to this forum maybe it's not even worth the trouble.

    :/

    Edit: I ended up including the source in my own code, clearly marking where it's from and its non-existing license etc. Thanks!
     
  9. Offline

    andune

    Though it's possible he's left the community, I just want to say thanks to LennardF1989 for providing this. I use Bukkit persistence in my plugin (HomeSpawnPlus) and it has annoyed me to no end that I cannot live-reload my plugin to do live updates to my server, like I can with every other plugin that doesn't use Bukkit persistence. Switching over to Bukkit-persistance-reimplemented has allowed me to finally take advantage of live-reloading for HSP and it's so much easier/faster to test both locally and update my prod server without requiring reboots now. I really appreciate the time LennardF1989 put into making this, it's a big help.
     
  10. Offline

    LennardF1989

    Nah, I'm still here! Just took a small break from a lot of community activity so real-life could catch up with me.

    If you still have any problems, let me know!

    EDIT: The Maven repo is now up to date again.
     
    troed likes this.
  11. Offline

    bob3695

    LennardF1989

    I am working on using Persistence (started with the bukkit persistence then just switched to your implementation) in a new plugin I am working on and have a entity class:

    http://pastebin.com/ZMx9eL3d

    I have many other classes that are similar and save with no issue, but when I try and save this particular one I always get errors like this:

    Code:
    19:16:15 [SEVERE] javax.persistence.PersistenceException: ERROR executing DML bindLog[] error[Lock wait timeout exceeded; try restarting transaction]
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:116)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.insert(DmlBeanPersister.java:76)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.persist.DefaultPersistExecute.executeInsertBean(DefaultPersistExecute.java:91)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.core.PersistRequestBean.executeNow(PersistRequestBean.java:527)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.core.PersistRequestBean.executeOrQueue(PersistRequestBean.java:557)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.java:404)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.persist.DefaultPersister.saveVanillaInsert(DefaultPersister.java:377)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.persist.DefaultPersister.saveVanillaRecurse(DefaultPersister.java:361)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.persist.DefaultPersister.saveRecurse(DefaultPersister.java:308)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.persist.DefaultPersister.save(DefaultPersister.java:282)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1577)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1567)
    19:16:15 [SEVERE]    at com.bob3695.AgeOfMinecraft.AOMDatabase.Cache.Base.Cache.save(Cache.java:41)
    19:16:15 [SEVERE]    at com.bob3695.AgeOfMinecraft.AOMDatabase.DataAccess.CivDataAccess.save(CivDataAccess.java:74)
    19:16:15 [SEVERE]    at com.bob3695.AgeOfMinecraft.AOMDatabase.Main.AOMDatabase$1.run(AOMDatabase.java:35)
    19:16:15 [SEVERE]    at org.bukkit.craftbukkit.scheduler.CraftWorker.run(CraftWorker.java:34)
    19:16:15 [SEVERE]    at java.lang.Thread.run(Thread.java:680)
    19:16:15 [SEVERE] Caused by: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
    19:16:15 [SEVERE]    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
    19:16:15 [SEVERE]    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3593)
    19:16:15 [SEVERE]    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3525)
    19:16:15 [SEVERE]    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1986)
    19:16:15 [SEVERE]    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2140)
    19:16:15 [SEVERE]    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2626)
    19:16:15 [SEVERE]    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2111)
    19:16:15 [SEVERE]    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2407)
    19:16:15 [SEVERE]    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2325)
    19:16:15 [SEVERE]    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2310)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.lib.sql.ExtendedPreparedStatement.executeUpdate(ExtendedPreparedStatement.java:164)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.type.DataBind.executeUpdate(DataBind.java:74)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.persist.dml.InsertHandler.execute(InsertHandler.java:155)
    19:16:15 [SEVERE]    at com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:105)
    19:16:15 [SEVERE]    ... 16 more
    Any ideas?
     
  12. Offline

    LennardF1989

    Hiya, at frist, be sure you registered the class with Ebeans!

    Then I would start by commenting out the OneToOne, OneToMany, etc. annotations - in such a way they are not persisted. My guess is it goes wrong there somewhere - my wild guess is it's the OneToOne's together with the JoinColumns.

    Start by removing those, as much of a pain it will be.

    With all the ORM's I've worked with, OneT0X mappings are always extremely sensitive.

    EDIT: Be sure to not have duplicate field names when joining! Also keep in mind that the error could come from one of the mapped classes as well. Not sure if you did, but try persisting them one by one, working your way up.
     
  13. Offline

    bob3695

    LennardF1989

    Well while waiting I went ahead and commented out ALL of the fields except for the id, rebuilt the db and tried to save basically an empty entity (it only has id now!) and it still times out when saving.

    EDIT: When I tried it on my hosted server I had a different result... looks like it is getting hung on a select statement? I grabbed that statement and ran it against the db and came up in a matter of a second with no issues so I am not sure...

    Show Spoiler
    Code:
    entity id 550 at ([world] 286.930465601996, 74.0, -25.036000061938864)
    2012-04-18 20:45:03 [INFO] DataSourcePool [jdbcmysql66225198663306bob3695] grow; id[jdbcmysql66225198663306bob3695.2] busy[3] max[20]
    2012-04-18 20:46:12 [SEVERE] FATAL: DataSourcePool [jdbcmysql66225198663306bob3695] is down!!!
    com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
     
    The last packet successfully received from the server was 49,145 milliseconds ago.  The last packet sent successfully to the server was 75 milliseconds ago.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:407)
    at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116)
    at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3082)
    at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2968)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3516)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1986)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2140)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2620)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2570)
    at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1474)
    at com.avaje.ebeaninternal.server.lib.sql.DataSourcePool.testConnection(DataSourcePool.java:497)
    at com.avaje.ebeaninternal.server.lib.sql.DataSourcePool.checkDataSource(DataSourcePool.java:356)
    at com.avaje.ebeaninternal.server.lib.sql.DataSourceManager.checkDataSource(DataSourceManager.java:228)
    at com.avaje.ebeaninternal.server.lib.sql.DataSourceManager.access$100(DataSourceManager.java:37)
    at com.avaje.ebeaninternal.server.lib.sql.DataSourceManager$Checker.run(DataSourceManager.java:240)
    at com.avaje.ebeaninternal.server.lib.BackgroundThread$Runner.runJobs(BackgroundThread.java:208)
    at com.avaje.ebeaninternal.server.lib.BackgroundThread$Runner.run(BackgroundThread.java:172)
    at java.lang.Thread.run(Thread.java:722)
    Caused by: java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
    at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2529)
    at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2979)
    ... 15 more
    2012-04-18 20:46:12 [INFO] Reseting DataSourcePool [jdbcmysql66225198663306bob3695] min:2 max:20 free:1 busy:2 waiting:0 highWaterMark:3 waitCount:0 hitCount:1361
    2012-04-18 20:46:12 [INFO] PSTMT Statistics: name[jdbcmysql66225198663306bob3695.1] startTime[1334796342190] pstmtHits[663] pstmtMiss[34] jdbcmysql66225198663306bob3695.1 size:19 max:20 totalHits:663 hitRatio:47 removes:15
    2012-04-18 20:46:12 [INFO] Closing Connection[jdbcmysql66225198663306bob3695.1] psReuse[663] psCreate[34] psSize[19]
    2012-04-18 20:46:12 [INFO] Busy Connections:
    name[jdbcmysql66225198663306bob3695.2] startTime[1334796372248] stmt[null] createdBy[null]
    name[jdbcmysql66225198663306bob3695.0] startTime[1334796282662] stmt[select t0.id c0, t0.building_level c1, t0.being_built c2, t0.being_taken_down c3, t0.being_upgraded c4, t0.decaying c5, t0.built c6, t0.build_rate c7
    from aom_civ_buildings t0] createdBy[null]
     
    2012-04-18 20:46:12 [INFO] Closing Connection[jdbcmysql66225198663306bob3695.2] psReuse[623] psCreate[4] psSize[4]
    2012-04-18 20:46:12 [SEVERE] Closing Connection[jdbcmysql66225198663306bob3695.2] that is already closed?
    2012-04-18 20:46:22 [SEVERE] RESOLVED FATAL: DataSourcePool [jdbcmysql66225198663306bob3695] is back up!
    2012-04-18 20:46:22 [INFO] Reseting DataSourcePool [jdbcmysql66225198663306bob3695] min:2 max:20 free:0 busy:1 waiting:0 highWaterMark:3 waitCount:0 hitCount:1362
    2012-04-18 20:46:22 [INFO] Busy Connections:
    name[jdbcmysql66225198663306bob3695.0] startTime[1334796282662] stmt[select t0.id c0, t0.building_level c1, t0.being_built c2, t0.being_taken_down c3, t0.being_upgraded c4, t0.decaying c5, t0.built c6, t0.build_rate c7
    from aom_civ_buildings t0] createdBy[null]
     
    2012-04-18 20:46:22 [INFO] DataSourcePool [jdbcmysql66225198663306bob3695] grow; id[jdbcmysql66225198663306bob3695.3] busy[2] max[20]
    2012-04-18 20:46:22 [INFO] Closing Connection[jdbcmysql66225198663306bob3695.3] psReuse[0] psCreate[0] psSize[0]
    2012-04-18 20:46:42 [INFO] DataSourcePool [jdbcmysql66225198663306bob3695] grow; id[jdbcmysql66225198663306bob3695.4] busy[2] max[20]
    2012-04-18 20:47:12 [SEVERE] FATAL: DataSourcePool [jdbcmysql66225198663306bob3695] is down!!!
    com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
     
    The last packet successfully received from the server was 30,018 milliseconds ago.  The last packet sent successfully to the server was 0 milliseconds ago.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:407)
    at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116)
    at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3082)
    at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2968)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3516)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1986)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2140)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2620)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2570)
    at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1474)
    at com.avaje.ebeaninternal.server.lib.sql.DataSourcePool.testConnection(DataSourcePool.java:497)
    at com.avaje.ebeaninternal.server.lib.sql.DataSourcePool.checkDataSource(DataSourcePool.java:356)
    at com.avaje.ebeaninternal.server.lib.sql.DataSourceManager.checkDataSource(DataSourceManager.java:228)
    at com.avaje.ebeaninternal.server.lib.sql.DataSourceManager.access$100(DataSourceManager.java:37)
    at com.avaje.ebeaninternal.server.lib.sql.DataSourceManager$Checker.run(DataSourceManager.java:240)
    at com.avaje.ebeaninternal.server.lib.BackgroundThread$Runner.runJobs(BackgroundThread.java:208)
    at com.avaje.ebeaninternal.server.lib.BackgroundThread$Runner.run(BackgroundThread.java:172)
    at java.lang.Thread.run(Thread.java:722)
    Caused by: java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
    at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2529)
    at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2979)
    ... 15 more
    2012-04-18 20:47:12 [INFO] Reseting DataSourcePool [jdbcmysql66225198663306bob3695] min:2 max:20 free:0 busy:2 waiting:0 highWaterMark:3 waitCount:0 hitCount:1364
    2012-04-18 20:47:12 [INFO] Busy Connections:
    name[jdbcmysql66225198663306bob3695.4] startTime[1334796432416] stmt[null] createdBy[null]
    name[jdbcmysql66225198663306bob3695.0] startTime[1334796282662] stmt[select t0.id c0, t0.building_level c1, t0.being_built c2, t0.being_taken_down c3, t0.being_upgraded c4, t0.decaying c5, t0.built c6, t0.build_rate c7
    from aom_civ_buildings t0] createdBy[null]
     
    2012-04-18 20:47:12 [INFO] Closing Connection[jdbcmysql66225198663306bob3695.4] psReuse[0] psCreate[0] psSize[0]
    2012-04-18 20:47:12 [SEVERE] Closing Connection[jdbcmysql66225198663306bob3695.4] that is already closed?
    2012-04-18 20:47:22 [SEVERE] RESOLVED FATAL: DataSourcePool [jdbcmysql66225198663306bob3695] is back up!
    2012-04-18 20:47:22 [INFO] Reseting DataSourcePool [jdbcmysql66225198663306bob3695] min:2 max:20 free:0 busy:1 waiting:0 highWaterMark:3 waitCount:0 hitCount:1365
    2012-04-18 20:47:22 [INFO] Busy Connections:
    name[jdbcmysql66225198663306bob3695.0] startTime[1334796282662] stmt[select t0.id c0, t0.building_level c1, t0.being_built c2, t0.being_taken_down c3, t0.being_upgraded c4, t0.decaying c5, t0.built c6, t0.build_rate c7
    from aom_civ_buildings t0] createdBy[null]
     
    2012-04-18 20:47:22 [INFO] DataSourcePool [jdbcmysql66225198663306bob3695] grow; id[jdbcmysql66225198663306bob3695.5] busy[2] max[20]
    2012-04-18 20:47:22 [INFO] Closing Connection[jdbcmysql66225198663306bob3695.5] psReuse[0] psCreate[0] psSize[0]
    2012-04-18 20:47:38 [INFO] DataSourcePool [jdbcmysql66225198663306bob3695] grow; id[jdbcmysql66225198663306bob3695.6] busy[2] max[20]


    It is worth noting, on the hosted server the data actually saves. So it might not actually be the save, but rather something I do before a save.
     
  14. Offline

    ronzi3

    Hi, sorry for my english, just want to ask a few questions:

    1_ Is it possible to save lists containing primitive types (like String, Integer, etc) using your inplementation?
    I can't save List<String> with bukkit default ebean implementation, A runtime exception appears saying that the class String is not registered, even using all variations of "@CollectionOfElements" annotation.

    2_ What about those performance issues "phaed" was mentioning earlier?
    This is like pushing me to learn direct SQL code to handle my plugin's persistence... I wouldn't like to have those performance problems. Phaed is a great plugin autor, I use many of his plugins, so I trust in what he says :)

    I think this bukkit built in ebean persitence is not for all kind of projects, I need to save primitive type lists and it seems that is not supported, also I needed to save a Map<String, Map<String, Integer>> and found that is not possible...
    Please give me some advices since you seem to be very familiar with persistence processes, thanks in advance.
     
  15. Offline

    jast

    What you probably want to and should do, is not save these data structures directly, but rather decompose them into a relational model. A List of strings is essentially a table with a single column. A Map<String,Integer> is a table with two columns, string and integer respectively, where the string column is also the key. A Map<String, Map<String, Integer>> might be represented as a table with 3 columns, where the 2 string columns are the keys.
     
  16. Offline

    TerraVale

    This thread seemingly has the worst necro bumps I've ever seen in my lifetime :confused:
     
  17. Offline

    jast

    I choose to disregard the convention against "necro bumps" sometimes :)
     
    TerraVale likes this.
Thread Status:
Not open for further replies.

Share This Page