How to parse message for a log4j2 JDBC Appender - java

In my application, I use a pre determined log messages, something like this:
MESSAGE_ID PROCESS_ID This process is running
I would like to use a JDBC Appender and split my message in three, to get put each part in a particular SQL column.
Is this possible? And How?
Thanks a lot!

One idea is to use the ThreadContext to carry the message ID and process ID, and declare jdbc columns for each item like this:
<Column name="MESSAGE" pattern="%message" />
<Column name="MESSAGE_ID" pattern="%X{messageID}" />
<Column name="PROCESS_ID" pattern="%X{processID}" />
In your code you set the values like this:
ThreadContext.put("messageID", UUID.randomUUID().toString();
ThreadContext.put("processID", getProcessId());
...
logger.debug("this process is running");
...

Related

Esper Database Adapter insert Data to mysql database?

I am new to esper. I want to store in mysql database event when esper identify event which satisfy the eql query.First i look up this example Esper: How to configure Esper to connect a Relational Database, through a JDBC, using Esper's configuration API and try to come up with solution.
<plugin-loader name="EsperIODBAdapter" class-name="com.espertech.esperio.db.EsperIODBAdapterPlugin">
<config-xml>
<esperio-db-configuration>
<jdbc-connection name="database">
<drivermanager-connection class-name="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/CEP_DEMO"
user="user" password="password"/>
<connection-settings auto-commit="true" catalog="TEST"/>
</jdbc-connection>
<dml connection="database" stream="event" >
<sql>INSERT INTO BasicEvent(userId,eventId,eventUsage,eventDateTime) values(?,?,?,?) </sql>
<bindings>
<bindings>
<parameter pos="1" property="userId"/>
<parameter pos="2" property="eventId"/>
<parameter pos="3" property="eventUsage"/>
<parameter pos="4" property="eventDateTime"/>
</bindings>
</bindings>
</dml>
</esperio-db-configuration>
</config-xml>
</plugin-loader>
Then when i run the application it didn't insert data to table.I want to know my method is correct or is there any other method to configuration.
Thanks
Maybe check that no exceptions are logged or thrown and the you are indeed inserting into a stream called "event" with "insert into event ..."

Hibernate slqjdbc4 column with spaces

I need to map in Java with hibernate a table in sqlserver that has spaces in the column names.
I use Sqlserver 2008 jre7 com.microsoft.sqlserver.sqljdbc4 with Hibernate 3.3.2
I found a lot of similar questions in different forums but none of the solutions I read worked.
I tried using the backtick
<property name="nameSpaces" type="string" >
<column name="`Name with spaces`" not-null="false" />
</property>
this is the error
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '`'.
I also tried to use the [] brakets but hibernate converted it in ` again.
<column name="[Name with spaces]" not-null="false" />
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '`'.
Finally I also tried both of them
<column name="`[Name with spaces]`" not-null="false" />
or
without success.
Can someone help me? Is there any hibernate configuration I can change to work with these column names.
Thanks
The answer (by BilalDja) is hidden above in a comment. I found his answer helpful so I thought I would add the answer here for others with the same problem.
This issue is hard to debug, I had to dig really deep into the hibernate and jdbc code to finally find the "real" SQL statement that is created to get data from the database. I then copied its value and ran it manually on my SQL Server database. Straight away the syntax error was obvious and sure enough it was cause by a space in a column name.
To fix this I just escaped the double quotes around the problematic column name as explained in BilalDja's comments and expanded slightly here...
#Column(name = "\"Column name\"")
private String variableColumnWillMapTo;
That's it, problem solved, no more syntax error.

Can't persist emojis with mysql and hibernate

I have actually found this problem multiple times on Stackoverflow, but the solutions would not help me.
I have a chat module in my android app and want to persist the messages in my server db, which works fine until special characters like emojis appear.
ERROR: Incorrect string value: '\xF0\x9F\x98\x81' for column 'message' at row 1
...
...
Caused by: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x81' for column 'message' at row 1
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1084)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4232)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4164)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2776)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2838)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2082)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2334)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2262)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2246)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:187)
... 23 more
My environment is:
-Mysql 5.6
-Tomcat 8.0.8
-Hibernate 4.3.5
-JDK 1.8.0_05
This is the used table with the column in question, 'message':
These are my properties in the persistence.xml (version 2.1):
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/gamedb?useUnicode=true&characterEncoding=UTF-8" />
<property name="javax.persistence.jdbc.user" value="*********" />
<property name="javax.persistence.jdbc.password" value="**************" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<property name="hibernate.connection.useUnicode" value="true" />
<property name="hibernate.connection.characterEncoding" value="utf8" />
Now I tried the following solutions without effect:
-Change datatype of 'message' from varchar to longtext
-Change collation of 'message' to utf8mb4
-Change collation of table to utf8mb4
-Append url with "?useUnicode=true&characterEncoding=UTF-8"
-Set character-set-server of mysql to utf8mb4
I think the emoji is correctly transmitted to the server, before it persists the message it broadcasts it back to the app and it gets correctly displayed.
I once had the same problem. I don't know a pretty solution but this had worked for me.
After I created the Session object I changed the connection collation by hand:
s.doReturningWork(new ReturningWork<Object>() {
#Override
public Object execute(Connection conn) throws SQLException
{
try(Statement stmt = conn.createStatement()) {
stmt.executeQuery("SET NAMES utf8mb4");
}
return null;
}
});
if you are using hibernate with c3p0, you can use c3p0 config connectionCustomizerClassName whitch you can set to a class doing work with connections c3p0 got.
example:
hibernate.cfg.xml
<property name="hibernate.c3p0.connectionCustomizerClassName">com.hzmoyan.newlyappserver.db.C3p0UseUtf8mb4</property>
C3p0UseUtf8mb4 class
public class C3p0UseUtf8mb4 extends AbstractConnectionCustomizer{
#Override
public void onAcquire(Connection c, String parentDataSourceIdentityToken)
throws Exception {
super.onAcquire(c, parentDataSourceIdentityToken);
try(Statement stmt = c.createStatement()) {
stmt.executeQuery("SET NAMES utf8mb4");
}
}
}
The solution is to use utf8mb4 rather than utf8 in MySQL. The blog post I linked to explains how to do just that.
I just found a nice little hack to get this to work without having to add any code. If you set the validation query to be SET NAMES utf8mb4 then it will execute this when it gets the connection, therefore setting the parameter each time a new connection is retrieved. You also need test on borrow to make this work.
Note I have found that this can sometimes take a few seconds to work after a restart so could have failures if you have records waiting to be processed on startup
So in your application.properties you would add something like
datasource.test-on-borrow=true
datasource.validation-query=SET NAMES utf8mb4
I was able to fix the issue by providing the following in my connection URL;
useUnicode=true&characterEncoding=UTF-8
Example;
jdbc:mysql://localhost/database?useUnicode=true&characterEncoding=UTF-8
Maybe you need to modify hibernate configuration as
<property name="hibernate.connection.characterEncoding" value="utf8mb4" />
If your datasource is org.apache.commons.dbcp.BasicDataSource you can set connectionInitSqls parameter
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"
p:testOnBorrow="true"
p:maxActive="1000"
p:testWhileIdle="true"
p:validationQuery="SELECT 1"
p:validationQueryTimeout="5">
<property name="connectionInitSqls">
<list>
<value>SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'</value>
</list>
</property>
</bean>
After not receiving further answers to my comments I found an alternative solution: Base64.
Instead of teaching my DB to understand utf8mb4 I encode all critical messages to Base64 before storing them and decode them when retrieving them from the database.
Pro:
- Works great
- Libraries are already given for java and android
Contra:
- Base64 strings take up more space than the pure utf8mb4 strings (33%-36% more)
- May cost some performance encoding and decoding

HQL search within child SET with IN keyword

i really can not find enough documentation on hibernate IN keyword, when applied on search within a collection of some object. I have strange problem, I have a hql query:
FROM Contact co, IN (co.categories)categories WHERE categories.name = ?
In i was expecting list of Contacts ofcourse. But something is wrong with it, because it is not returning list of Contact objects, but list of Object[]????? Is it syntax or this is totally wrong??
Here are mapping parts:
<set lazy="false" name="categories" table="ContactCategory">
<key column="id" foreign-key="fk_contact_category" />
<many-to-many class="Category" column="catid"
foreign-key="fk_contact_category2" />
</set>
<class name="Category">
<id column="catid" name="Id" type="long">
<generator class="sequence" />
</id>
<property length="50" name="name" type="string" />
</class>
Important thing to mention: This query is made with the query builder. This is printout of one of generated queries where its failing. Very weird is that - i am getting the correct number of objects in this list, I check the database and number is correct with given parameters, but I dont get Contact objects, but some Object arrays in the List.
Appreciate all the help
You need to add SELECT co
so that your Query is SELECT co FROM Contact co, IN (co.categories)categories WHERE categories.name = ?
The SELECT co is necessary, to tell Hibernate which one item it should return per result set line.
SELECT co FROM Contact co LEFT JOIN co.categories cat WHERE cat.name = ?
I have seen the IN keyword only in the Where - clause so far. In Stuff like this,
FROM catagories cat WHERE cat.name IN ('HALLO', 'WORLD')
I dont like answering my question, without really understanding why this SELECT is neccessary, but this works as a charm. If someone explains me reasoning, I would be happy to vote his answer.
**SELECT co** FROM Contact co, IN (co.categories)categories WHERE categories.name = ?
Thank you all
Julia, try printing the class and value of each object in the array of your original query like this:
List<Object[]> results = // code to fetch your query ;
// just the first, or you can print every entry with a outer loop
Object[] firstObject = results.get(0);
for (Object o : firstObject) {
System.out.println(o.getClass() + " - " + o);
}
My guess is that hibernate is inferring either a Contact object and a separate Category list or is bringing columns returned from the query as primitive wrappers. Anyway, the problem seems to be that Hibernate could not figure out what you were expecting to fetch from the the list of columns that were returned by the DBMS. In the second query you narrowed it down to an alias of the specific type you wanted, so everything worked as expected.
This worked for me in Grails 2.1.4 HQL
Task.executeQuery("
select task from Task task join task.tags tag where tag.name = 'duplicate' ")
assuming the entity Task.groovy has
static hasMany = [tags: Tag]

Google App Engine Error: No matching index found. (Java)

I am writing a query but it always says "No matching index found". I don't know why. My code is as below:
Query query = pm.newQuery(Classified.class);
query.setFilter("emp_Id == emp");
query.setOrdering("upload_date desc");
query.declareParameters("String emp");
List<Classified> results = (List<Classified>)query.execute(session.getAttribute("emp_Id").toString());
<?xml version="1.0" encoding="utf-8"?>
<datastore-indexes autoGenerate="true">
<datastore-index kind="Classified" ancestor="false">
<property name="emp_Id" direction="asc" />
<property name="category" direction="asc" />
<property name="upload_date" direction="desc" />
</datastore-index>
</datastore-indexes>
I have added the above index, but it did not help.
I believe you need to configure a Datastore Index. There's probably one already generated for you in Eclipse at WEB-INF/appengine-generated/datastore-indexes-auto.xml that you just need to copy to WEB-INF/datastore-indexes.xml and deploy again.
Because this needs to be somewhere on the internet...
I kicked myself when I found this out
The error is you do not have a index matching what the query would like to perform. You can have multiple indexes for each entity.
In the Logcat, error, it will tell you exactly what index to set and what order the elements need to be.
ie, if the error says it wants (it wont be nicely formatted):
<datastore-index kind="Classified" ancestor="false">
<property name="category" direction="desc" />
<property name="upload_date" direction="desc" />
</datastore-index>
then Project -> war -> WEB-INF -> appengine-generated -> datastore-indexes-auto.xml and add exactly that. Then, redeploy the project.
Next go into your Google Cloud Console and look at Datastore -> indexes. It should say that the index is being prepared (This goes quicker if you can kill all apps connected and shut down the instance in the console).
Once this has moved into the list of other indexes, rerun the your application and it wont error out with regards to the index anymore.
Go get it Gentlemen/Ladies
The index you define must hold all possible results in the order they will be returned. Your query asks for a particular emp_Id, ordered by upload_date, but your index is ordered primarily by category.
Try removing the category line from your index definition, or swapping the order of category and upload_date, to make upload_date the primary sort order for the index. If another part of your code relies on the category line, you may have to make two separate indices (which incurs some computational cost).
Edit: see comment below by Nick Johnson re. extra parameters.
I am running into this issue at the moment when doing a single property query such as:
const query = datastore
.createQuery('Emailing_dev')
.filter('status', '=', 'Scheduled')
In my case, I should not be getting any errors, however I get Error 9: No matching index found.
If I defined the single property index twice in the yaml, it works:
indexes:
- kind: Emailing_dev
properties:
- name: status
- name: status
but this for sure must be a bug..!!

Categories