
v0.2.35.XXXapplication.ymlplainjava -jar .\DrawAndChatApp-0.2.35.2-SNAPSHOT.jar --spring.config.additional-location=.\application.ymlDrawAndChatApp - Session init & control Page will open upNewUseSend - Hostapplication.yml
cpy.rf.ntt.drc:
det-DisableReceiveNetworkMsg-Kafka: false
kafka:
bootstrap.servers: "localhost:9092" # @edit_this[base on your Config]profiles.active: "plain, Enable_ReceiveNetworkMsg"ClearAllMsg_InKafkaTopicNewUseSend - Host
On Guest side - Click the Button ReceiveNetworkMsg - Guestdb_drawandchat_01 / db_drawandchat_02) &Drc_NodeEvent_All-Host & Drc_NodeEvent_All-Guest)com.redfrog.note.database.DbThreadHelper.clear_TabelRows_db01()
public static final String queryStrf_GetAllTableName = "SELECT table_name FROM information_schema.tables WHERE table_schema = '%s';";
public static final String queryStrf_RemoveAllRowInATable = "TRUNCATE TABLE %s;";
public static final String tableName_hibernate_sequence = "hibernate_sequence";
@Transactional(value = "txm_01")
public List<String> clear_TabelRows_db01() {
Query query_GetAllTableName = em_01.createNativeQuery(String.format(queryStrf_GetAllTableName, DbName.db_drawandchat_01));
List<String> resultList_AllTableName = query_GetAllTableName.getResultList();
System.out.println(">> clear_TabelRows_db01() :: " + DbOccupation.DbName.db_drawandchat_01 + " :: " + Thread.currentThread().getName() + " :: " + resultList_AllTableName + " :: " + em_01);
if (resultList_AllTableName.size() > 5) {
String msg = "Seems deleting a lot of tables es rows? Is this Sql correct? :: numTable=" + resultList_AllTableName.size();
System.out.println(msg);
throw new Error(msg);
}
for (String tableName : resultList_AllTableName) {
if (!tableName.equals(tableName_hibernate_sequence)) {
Query query_RemoveAllRowInATable = em_01.createNativeQuery(String.format(queryStrf_RemoveAllRowInATable, tableName));
query_RemoveAllRowInATable.executeUpdate();
}
else {
System.out.println("Do nothing with table :: " + tableName_hibernate_sequence);
}
}
return resultList_AllTableName;
}
com.redfrog.note.util.KafkaUtil.clear_AllMsg_debug(KafkaConfig)
public static void clear_AllMsg_debug(KafkaConfig kafkaConfig) {
String msg = "The way clear_AllMsg() implemented is very bad -- delete Records in a Kafka topic is possible, "
+ "\n" + "but doesnt have a good API in Java (-- missing sufficient info to get Access to the Partition & the Offset of the Message).";
System.out.println(msg);
System.err.println(msg);
Consumer<String, ? extends Object> kConsumer_AnyRecord = new KafkaConsumer<>(kafkaConfig.kProp_Consumer);
kConsumer_AnyRecord.subscribe(Arrays.asList(kafkaConfig.kTopicName_Send_NodeEvent_All, kafkaConfig.kTopicName_Receive_NodeEvent_All));
while (true) {
try {
ConsumerRecords<String, ? extends Object> consumerRecords = kConsumer_AnyRecord.poll(Duration.ofMillis(1200));
if (consumerRecords.isEmpty()) {
System.out.println("Seems all msg drained.");
kConsumer_AnyRecord.close();
break;
}
for (ConsumerRecord<String, ? extends Object> consumerRecord : consumerRecords) {
System.out.println("Draining :: " + consumerRecord); //
}
} catch (WakeupException e) {
System.out.println("Seems we are shutting down :: " + e);
kConsumer_AnyRecord.close();
}
}
}
mysqldump -u USERNAME -pPASSWORD DBNAME > /path/to/location/backup.sqlsee https://stackoverflow.com/questions/4283168/how-can-i-backup-a-mysql-database-from-java
mysql -u USERNAME -pPASSWORD --database DBNAME < /path/to/location/backup.sql
application.yml
spring:
config:
activate:
on-profile: "Enable_LoadSaveFile | prod"
ds-mysql-01:
driver-class-name: com.mysql.cj.jdbc.Driver
hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
jdbc-url: jdbc:mysql://localhost:3306/db_drawandchat_01 # @edit_this[base on your Config] # database name is hardcoded (seems); (other type of database (not mysql) may not be supported);
password: mysql # @edit_this[base on your Config]
username: root # @edit_this[base on your Config]
ds-mysql-02: # db02 is mainly for debugging
driver-class-name: com.mysql.cj.jdbc.Driver
hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
jdbc-url: jdbc:mysql://localhost:3306/db_drawandchat_02 # @edit_this[^]
password: mysql # @edit_this[^] # password & username should be same as db01
username: root # @edit_this[^]
cpy.rf.ntt.drc:
det-DisableLoadSaveFile-Mysql: false
loadSaveFile:
pathStr-drcFileSave: "H:\\DrawAndChatApp_db" # @edit_this[base on your Config] # default path for save & load the file
pathStr-mysqldump: "C:\\Program Files\\MySQL\\MySQL Server 8.0\\bin\\mysqldump.exe" # @edit_this[base on your Config] # path to mysqldump
pathStr-mysql: "C:\\Program Files\\MySQL\\MySQL Server 8.0\\bin\\mysql.exe" # @edit_this[base on your Config] # path to mysql # you can just put `mysql` if your env var is properly set (seems)
profiles.active: "plain, Enable_LoadSaveFile"NewUseSend - HostEditing File Windowem.persist() is slow & may still be going in the background (just for Saving your file)10s ~ 40s+ ~ ?s to finish all persist."Auto Close When Sql persist is Done "."Force Close Right Now ".SaveFile (in DrawAndChatApp - Session init & control Page)Session init Page (close the App)Force use given dbdb_drawandchat_01)ClearAllTableRows_InGivenDb
public static final String TextWarn_OverwriteOrAppendDb =
"""
[Warning: 80% - @datalost] det_ExistDataIn_EntityGeneral != 0; for db :: %s
Detected Existing Old Data in this Db.
"""
+ Text_ClearAllTableRows_InGivenDb +
"""
Basing on your selection on det_AllowDbOverwriteOrAppend :: %s
If true:
-> New Data will be Appended to the Existing Old Data - for New session / Receive session.
-> Existing Old Data will be Cleared, New Data will be Written to an empty/cleared database - for Load session.
If false:
-> Throw an Error, Session Abort, No data are cleared or written.
""";LoadSaveFile - Hostapplication.ymlprofiles.active: "Enable_ReceiveNetworkMsg, Enable_LoadSaveFile"NewUseSend - Host /ReceiveNetworkMsg - GuestEditing File WindowSaveFile (in DrawAndChatApp - Session init & control Page)Session init Page (close the App)Force use given dbdb_drawandchat_01db_drawandchat_02db_drawandchat_02,ClearAllTableRows_InGivenDbLoadSaveFile - Host /ReceiveNetworkMsg - GuestDrawAndChatVm is the central -- of this ProjectNodeSender_ConvertWrapper & NodeSender_EventAnnouncer are the central -- of DataCommunicationNodeSig & NodeEvent are the backbone data structure -- of all the Node & NodeEvent (all the business objects)SessionManager & WindowSession is the central -- for the management & linkage across all the classes in the Project[NewUseSend, ReceiveNetworkMsg, LoadSaveFile]DrawAndChatAppSessionInit is the first contact when you start the AppDrawAndChatAppSessionInitSessionManagerWindowSessionDbOccupation to the SessionKafkaConfigDrawAndChatVmNodeSender_ConvertWrapper & NodeReceiver_EventListenerDrawAndChatVm_ReceiveNetworkMsg & DrawAndChatVm_LoadSaveFile are just variations of DrawAndChatVmDrawAndChatVmDrawAndChatVm -- deal with NewUseSend session (-- actually backbone of all Sessions)DrawAndChatVm_ReceiveNetworkMsg -- deal with ReceiveNetworkMsg sessionDrawAndChatVm_LoadSaveFile -- deal with LoadSaveFile sessionNodeSender_ConvertWrapper & NodeReceiver_ConvertHandler are the bridges between DrawAndChatVm & MessageQueue/DatabaseDrawAndChatVmNodeSender_ConvertWrapper > NodeSender_EventAnnouncerNodeReceiver_EventListener > NodeReceiver_ConvertHandlerNodeSender_ConvertWrapperJavafxNode to NodeSig / associate / find them in NodeSigManagerNodeCreatorAndConvertorJavafxNode to/from NodeSigNodeSender_EventAnnouncerNodeEventNodeEventDbThreadHelperMultipleDbSpringConfigSerializationUtilsSerializer & SerializationUtilsDeserializerNodeReceiver_EventListenerNodeEventNodeEventNodeReceiver_ConvertHandlerNodeEventThis App is built using a mechanism - Event Sourcing
-- every single action is sent by MsgBroker & persist into Database -- as an Event.
| Functionality | Hotkey | Description | Activated When | * |
|---|---|---|---|---|
| Freehand Drawing in Canvas | LButton (drag) | Focus on Canvas | ||
| create a Panel (+ a TextArea) | ^n | (nest supported) | Focus on Panel / Root Panel | |
| move a Node | ^!LButton (drag) | (You need to click on the PaneWrap of the Node) | Focus on PaneWrap of the Node | |
| remove a Node | delete | (You need to click on the PaneWrap of the Node) | Focus on PaneWrap of the Node | |
| focus on a Node | LButton | (You need to click on the PaneWrap of the Node) | Global | |
| draw an Arrow to link 2 Nodes | ^LButton RButton (to Cancel) | click on Node AA to Start & click on Node BB to End (note: its very thin & hard to be clicked to Focus on) | Focus on Panel / PaneWrap of the Node | |
| undo | ^z | (undo when focusing in TextArea is diff) | Focus on Panel / Root Panel | |
| redo | ^+z | Focus on Panel / Root Panel | ||
| clear Drawing in Canvas | RButton (drag) | Focus on Canvas | ||
| create a TextArea | ^+b | Focus on Panel / Root Panel | ||
| create a Canvas | ^m | Focus on Panel / Root Panel | ||
| type on TextArea (bi-dir) | (Tab to focus on) | Focus on TextArea | ||
| resize a Node | ^!LButton (drag, on the Resize_Handler) | Focus on Resize_Handler of the Node | ||
| move Layer of a Node | PgUp PgDn Home End | (Note: the Layer of the Canvas in the Background can be moved too) | Focus on PaneWrap of the Node | |
| zoom a Node | ^WheelUp ^WheelDown F1 | F1 reset the zoom | Focus on PaneWrap of the Node | |
| move the Background (Root Panel) | ^!MButton (drag) F4 | F4 reset the position | Global | |
| move the MiniMap | ^!LButton (drag) | Focus on the MiniMap | ||
| create a IndexCircle | ^i ^1 ^2 ^3 ^4 ^5 | ^i increment index by 1 ^1 reset index to 1 | Focus on Panel / Root Panel | |
| change Text on IndexCircle | (Tab & Type the Text) | Focus on the IndexCircle | ||
| copy a Node | Not supported | |||
| cut a Node | ^x | Focus on PaneWrap of the Node | ||
| paste a Node | ^v | cut a Node & Focus on Panel / Root Panel | ||
| change Pen Color of Canvas | !0 !1 !2 !3 !4 !5 !6 !7 !8 | !0 is the original blue color (Note: if the Canvas is not focused (to receive hotkey), you can Tab to focus on it) | Focus on Canvas | |
staticpublic@Scope("prototype") (but not sure how well it will do).@Inheritance(strategy = InheritanceType.JOINED)@Inheritance(strategy = InheritanceType.SINGLE_TABLE)@GeneratedValue(strategy = GenerationType.SEQUENCE)@OneToOne(cascade = { CascadeType.PERSIST }),Serializable Interface.Protobuf will be considered.plain is designed specifically for this case).application.yml is ready to use).java -jar .\DrawAndChatApp-0.2.35.2-SNAPSHOT.jar --spring.config.additional-location=.\application.yml