Unable to lookup jndi name tomcat 8.0 mybatis - servlets

I am using tomcat 8.0, mybatis 3.2.2, my application was working fine when I used datasource in mybatis-config.xml
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#localhost:1521:XE"/>
<property name="username" value="uid"/>
<property name="password" value="pwd"/>
</dataSource>
</environment>
I followed the procedure and solution given in many forums, particularly stachoverflow, but it didn't help. Here are the steps I followed. I have placed mysql-connector-java-5.1.38.jar under Tomcat8.0\lib and ojdbc6.jar under WEB-INF\lib folder. I am using java 1.8. Please help to identify where I missed
server.xml under Tomcat8.0\conf
<GlobalNamingResources>
<Resource name="jdbc/MYDB"
auth=Container
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.driver.OracleDriver"
username="uid"
password="pwd"
url="jdbc:oracle:thin:#localhost:1521:XE"
/>
Tomcat8.0\conf\context.xml
<Context>
<ResourceLink name="jdbc/MYDB" global="jdbc/MYDB" type="javax.sql.DataSource"/>
</Context>
web.xml within myapp/WebContent/WEB-INF/
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/MYDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
mybatis-config.xml with JNDI name reference
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="JNDI">
<property name="data_source" value="java:comp/env/jdbc/MYDB"/>
</dataSource>
</environment>
DBUtil.java has the below code
String resource = "path of mybatis-config.xml";
InputStream inputStream;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
But when I run the application(access the database), I get
Cause: java.sql.SQLException: Cannot create JDBC driver of class '' for connect URL 'null'
.
.
.
Caused by: java.lang.NullPointerException
at com.mysql.fabric.jdbc.FabricMySQLDriver.parseFabricURL(FabricMySQLDriver.java:97)
Please let me know where I have missed and whats the issue.

The main problem I see is that you are using a MySQL JDBC driver for an Oracle database. This is an Oracle Driver: oracle.jdbc.driver.OracleDriver and this is an oracle connection string: jdbc:oracle:thin:#localhost:1521:XE but you mention this:
I have placed mysql-connector-java-5.1.38.jar under Tomcat8.0\lib and ojdbc6.jar under WEB-INF\lib folder.
You need to place ojdbc6.jar (the JDBC driver for Oracle DB) under Tomcat8.0\lib and remove the mysql-connector-java-5.1.38.jar (a JDBC driver for MySQL DB).

Related

org.flywaydb.core.api.FlywayException: Error while determining database product name

below is my JNDI lookup for the Datasource
<bean id="datasource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/intdb" />
</bean>
and flyway bean config is
<bean id="flyway" class="org.flywaydb.core.Flyway" init-method="migrate">
<property name="dataSource" ref="datasource" />
</bean>
i am getting below exception, but if i replace JNDI lookup with all the properties in the bean it works fine,
Caused by: org.flywaydb.core.api.FlywayException: Error while
determining database product name
at org.flywaydb.core.internal.dbsupport.DbSupportFactory.getDatabaseProductName(DbSupportFactory.java:139)
at org.flywaydb.core.internal.dbsupport.DbSupportFactory.createDbSupport(DbSupportFactory.java:59)
at org.flywaydb.core.Flyway.execute(Flyway.java:1147)
at org.flywaydb.core.Flyway.migrate(Flyway.java:811)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1581)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1522)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
... 26 more
Caused by: java.sql.SQLException: Unsupported feature
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:179)
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:269)
at oracle.jdbc.dbaccess.DBError.throwUnsupportedFeatureSqlException(DBError.java:689)
at oracle.jdbc.OracleDatabaseMetaData.getDatabaseMajorVersion(OracleDatabaseMetaData.java:4442)
at org.flywaydb.core.internal.dbsupport.DbSupportFactory.getDatabaseProductName(DbSupportFactory.java:134)
I have got similar, working configuration in my project. In spring context XML I have got:
<bean id="migrationDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/myTestDb"/>
</bean>
<bean id="dbMigrationManager" class="test.version.DbMigrationManager" init-method="updateDatabaseSchema">
<constructor-arg name="migrationDataSource" ref="migrationDataSource"/>
</bean>
I am wrapping data source by constructor argument in DbMigrationManager. It looks like this:
package test.version;
import org.flywaydb.core.Flyway;
import javax.sql.DataSource;
public class DbMigrationManager {
private final DataSource dataSource;
public DbMigrationManager(DataSource migrationDataSource) {
this.dataSource = migrationDataSource;
}
public void updateDatabaseSchema() {
Flyway flyway = new Flyway();
flyway.setDataSource(dataSource);
flyway.migrate();
}
}
Also I am using Flyway 3.0 version in gradle like this:
compile group: 'org.flywaydb', name: 'flyway-core', version: '3.0'
If that do not help then maybe your problem is database specific. Like in this thread:
Exception against Oracle DB: "Error while determining database product name: Unsupported feature"
Or you are using some older, buggy version of Flyway.

Why isn't this code writing log output on my Tridion Content Delivery server?

I have a user control rendering content from a custom (non-Tridion) database. The connection string for this custom database is incorrect, and so I'm getting an SqlException when the code tries to connect.
My code is currently:
var logger =
Tridion.ContentDelivery.Web.Utilities
.LoggerFactory.GetLogger(this.GetType().ToString());
try
{
/* make a database connection - failing with SqlException */
}
catch (SqlException e)
{
logger.Error("Could not connect to database: " + e.ToString());
}
My \bin\config\logback.xml file contains:
<property name="log.pattern" value="%date %-5level %logger{0} - %message%n"/>
<property name="log.history" value="7"/>
<property name="log.folder" value="c:/tridion/log"/>
<property name="log.level" value="DEBUG"/>
...
<appender name="rollingCoreLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.folder}/cd_core.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>${log.history}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<prudent>true</prudent>
</appender>
...
<root level="warn">
<appender-ref ref="rollingCoreLog"/>
</root>
There's a stack of logs in C:\Tridion\log, but the most recently changed one was modified 20 minutes ago, and doesn't contain my log message text (I just did a search for "database" in notepad).
Why isn't my log output being sent to the log?
You have 2 options:
You define the root logging to "DEBUG" but this has the disadvantage that allows a huge amount of logging from all the third-party libraries that Tridion is using. Here is the snippet: <root level="DEBUG"> <appender-ref ref="rollingCoreLog"/> </root>
You define a special appender to include also the Tridion .NET logging: <logger name="Tridion.ContentDelivery" level="${log.level}"><appender-ref ref="rollingCoreLog"/></logger>
Note that in the second case you need your logger to be bound to a namespace under Tridion.ContentDelivery. Here is an example:
var logger =
Tridion.ContentDelivery.Web.Utilities.LoggerFactory.GetLogger("Tridion.ContentDelivery.MyNamespace.MyClass");
Hope this helps.
P.S.: to answer your question: because you do not have an appender for it and the root logging is set to WARN. By default, the logback.xml contains appenders only for "com.tridion" but I guess that the output of this.getType().ToString() does not start with that string.

Spring MVC JDBC DataSourceTransactionManager: Data committed even after readonly=true

I am currently developing a Spring MVC application.I have configured a JDBC TransactionManager and I am doing declarative transaction management using AOP XML.However, even if I configure the method to run on a read-only=true, it still commits the transaction.
Database : Oracle 10g
My database-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schem...ring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<property name="defaultAutoCommit" value="false" />
</bean>
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:com/mybatis/mappers/*.xml" />
</bean>
<!--
the transactional advice (what 'happens'; see the <aop:advisor/> bean
below)
-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true" />
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*" read-only="true" rollback-for="RuntimeException"/>
</tx:attributes>
</tx:advice>
<!--
ensure that the above transactional advice runs for any execution of
an operation defined by the FooService interface
-->
<aop:config>
<aop:pointcut id="fooServiceOperation"
expression="execution(* com.service.EmployeeService.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation" />
</aop:config>
</beans>
My controller
package com.service;
import java.util.List;
import com.mybatis.dao.EmployeeMapperInterface;
import com.spring.model.Employee;
public class EmployeeService implements EmployeeBaseService{
EmployeeMapperInterface employeeMapper;
public EmployeeMapperInterface getEmployeeMapper() {
return employeeMapper;
}
public void setEmployeeMapper(EmployeeMapperInterface employeeMapper) {
this.employeeMapper = employeeMapper;
}
#Override
public Employee getEmployeeById(long empId){
//retrieve from database
List empList = employeeMapper.getEmployeeWithId(empId);
if(empList != null && empList.size()>0){
return (Employee) empList.get(0);
}
return null;
}
#Override
public long saveEmployee(Employee employee){
long empId = 0l;
if(employee.getEmpId()==0){
empId = new Long( employeeMapper.insertEmployee(employee));
}else{
employeeMapper.updateEmployee(employee);
empId = employee.getEmpId();
}
try {
System.out.println("gonna sleep");
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
return empId;
}
How do I prevent the auto commit?I have also noticed that even if I don't put any transaction management code, the code still commits. Note, the transaction advice is however,invoked as when I put a no-rollback-for for RuntimeException and then do a 1/0, it correctly commits the data and rolls back if I put the same as rollback-for.
I have also tried out the query timeout by putting the thread on sleep, even that doesn't work, but I figure that timeout might be for an actual query, so thats fine.
Thanks in advance!
The advice read-only is only advice. It is not a requirement that the underlying transaction management system prevent writes when something is marked read-only, it is meant more as an optimization hint, saying that this method is read only, so you don't need to worry about it changing things. Some transaction managers will complain if changes are made in a read-only transaction, some will not. Generally, datasources acquired via JNDI will not. In any case, you should not rely on read-only advice preventing changes from being written back to disk.
Your options for preventing changes from being persisted are:
Mark the transaction rollback only or throw an exception having the same effect
Detach/evict the object from the transaction session before you change it
Clone the object and use the clone
DataSourceTransactionManager begins transaction with doBegin method.
From this method DataSourceUtils.prepareConnectionForTransaction called.
Inside this method you can see following code block:
if (definition != null && definition.isReadOnly()) {
try {
if (logger.isDebugEnabled()) {
logger.debug("Setting JDBC Connection [" + con + "] read-only");
}
con.setReadOnly(true);
}
catch (SQLException ex) {
So you could configure your logging framework to set log-level to DEBUG for DataSourceUtils class.
Or you could set breakpoint in this place and debug manually.
According to this article I expect that SET TRANSACTION READ ONLY will be executed on your Oracle connection.
And from Oracle docs we could see benefits which you receive in case of success:
By default, the consistency model for Oracle guarantees statement-level read consistency, but does not guarantee transaction-level read consistency (repeatable reads). If you want transaction-level read consistency, and if your transaction does not require updates, then you can specify a read-only transaction. After indicating that your transaction is read-only, you can execute as many queries as you like against any database table, knowing that the results of each query in the read-only transaction are consistent with respect to a single point in time.
The read-only behaviour is strictly driver specific. Oracle driver ignores this flag entirely. For instance the same update statements executed in Oracle will modify the database if run in read-only transaction, while in HSQL2 I was getting db level exceptions.
I know no other way than explicit rollback through api or exception to prevent commit in Oracle. Also this way your code will be portable between different drivers and databases.
The answer is on Spring MVC Mybatis transaction commit
Detailed stack traces are also available.
To summarize,
Read-only is only an advice and it guarantees nothing, and I would
really like the Spring docs to be updated about this.
whenever a query is executed in Oracle using Mybatis, it is in the context of a transaction which is automatically started,
committed(or rolled back, if execption is raised),and closed by
Mybatis.
Logging the application was a good idea and it helped me to find out how the actual transactions are started etc
.

how to marshal object and return as a view (and not as JSP page) in spring + xstream

I'm trying to follow this tutorial and build a RESTful service that can un/marshal an object to/from XML.
http://www.stupidjavatricks.com/?p=54
The marshaller of choice in the article is xStream (I found it to be very easy to use and configure).
The point is, using STS -- Spring's own flavor of Eclipse bundled with tcServer -- I built a project based on the STS template of MVC. This is a legacy project started from Spring version 2.4, and I migrated it to version 3.0. So, the template created all the necessary XML markup, and I added my configuration to point the view to the correct object conversion (to the xstream marshaler).
Here is part of my bean that sends the object to a new view (copied out from the link):
<bean id="bookXmlView" class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="autodetectAnnotations" value="true"/>
</bean>
</constructor-arg>
</bean>
It all worked nicely until I installed the latest STS version 2.5.2.RELEASE and created a new MVC project from a template. (The new template does not use urlrewrite.xml anymore, among some other changes).
I set the correct configuration 1 by 1 as the tutorial suggests, but now no matter what, the view is always directed to a JSP, so if my controller looks like this:
#RequestMapping(value = "/authors/{authorId}")
public ModelAndView getAuthorById(#PathVariable String authorId) {
Author author = bookService.getAuthorById(authorId);
ModelAndView mav =new ModelAndView("bookXmlView", BindingResult.MODEL_KEY_PREFIX+"author", author);
return mav;
}
It would always try to return to a author.jsp view and not the object as XML. I tried many things with no success. Any ideas why this happens and how to fix it?
UPDATE -------------------
As noted I added logs:
I set it as DEBUG level and discovered something:
DEBUG: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Rejected bean name 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor': no URL paths identified
DEBUG: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Rejected bean name 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor': no URL paths identified
DEBUG: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Rejected bean name 'org.springframework.context.annotation.internalRequiredAnnotationProcessor': no URL paths identified
DEBUG: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Rejected bean name 'org.springframework.context.annotation.internalCommonAnnotationProcessor': no URL paths identified
DEBUG: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Rejected bean name 'bookXmlView': no URL paths identified
Notice this line: Rejected bean name 'bookXmlView': no URL paths identified.
Searching this indicated maybe a clash between <mvc:annotation-driven /> and my autodetectAnnotations in the xstream settings?
Any case, after invoking the link, I got the following log entry. Notice it forwards the view to /WEB-INF/views/bookXmlView.jsp:
DEBUG: org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'appServlet' processing GET request for [/test/page_init]
DEBUG: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Mapping [/page_init] to HandlerExecutionChain with handler [test.test.test.HomeController#a087de] and 2 interceptors
DEBUG: org.springframework.web.servlet.DispatcherServlet - Last-Modified value for [/test/page_init] is: -1
DEBUG: org.springframework.web.bind.annotation.support.HandlerMethodInvoker - Invoking request handler method: public org.springframework.web.servlet.ModelAndView test.test.test.HomeController.getObject()
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'bookXmlView'
DEBUG: org.springframework.web.servlet.DispatcherServlet - Rendering view [org.springframework.web.servlet.view.JstlView: name 'bookXmlView'; URL [/WEB-INF/views/xmlView.jsp]] in DispatcherServlet with name 'appServlet'
DEBUG: org.springframework.web.servlet.view.JstlView - Added model object 'org.springframework.validation.BindingResult.books' of type [test.test.test.ObjectTest] to request in view with name 'bookXmlView'
DEBUG: org.springframework.web.servlet.view.JstlView - Forwarding to resource [/WEB-INF/views/xmlView.jsp] in InternalResourceView 'bookXmlView'
DEBUG: org.springframework.web.servlet.DispatcherServlet - Successfully completed request
Got it at last!
First I tried a different marshaller - JAXB2 but xstream should work as well.
Next thing is the definition - turns out for some reason the configuration uses this (wrong):
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
using only InternalResourceViewResolver
while definition for org.springframework.web.servlet.view.BeanNameViewResolver is ignored. The solution for that is to define them both in one bean called ContentNegotiatingViewResolver as follows:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</list>
</property>
</bean>
<oxm:jaxb2-marshaller id="marshaller">
<oxm:class-to-be-bound name="com.mycompany.dashboard.Person" />
</oxm:jaxb2-marshaller>
<bean name="person" class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg ref="marshaller" />
</bean>
That configuration solved my problems and person object I played with was not directed to a JSP view but marshaller turn is to an XML:
#RequestMapping(value = "/person", method = RequestMethod.GET)
public ModelAndView addPerson() {
Person person = new Person();
person.setAddress("address 123");
person.setAge(50);
person.setName("Andrew");
System.out.println("new person: " + person);
ModelAndView mav = new ModelAndView("person",BindingResult.MODEL_KEY_PREFIX + "person",person);
return mav;
Hope it would help others in the future too.

NLog - DDL for Log Table and Setting the ConnectionString Programmatically

1:
Is there a create statement for the Database Target Log Table for all the possible fields documented somewhere? I created one by guessing and I could check the source, but it would be handy if the generic SQL was available. I searched StackOverflow and the NLog site, but the SQL I found was dated and contained incorrect field types.
2:
If you're configuring a database target from a nlog.config file, how do you programmatically set the connection string? Something like:
Logger dbLogger = LogManager.GetLogger("dbLogger");
DatabaseTarget t = dbLogger.GetDatabaseTarget;
t.ConnectionString = "...";
in application_start.
Thanks in advance.
Is this below sample helpful to you? I found this in nlog site. Have you tried this?
<target xsi:type="Database" name="db">
<!-- SQL command to be executed for each entry -->
<commandText>INSERT INTO [LogEntries](TimeStamp, Message, Level, Logger) VALUES(getutcdate(), #msg, #level, #logger)</commandText>
<!-- parameters for the command -->
<parameter name="#msg" layout="${message}" />
<parameter name="#level" layout="${level}" />
<parameter name="#logger" layout="${logger}" />
<!-- connection string -->
<dbProvider>System.Data.SqlClient</dbProvider>
<connectionString>server=.\SQLEXPRESS;database=MyLogs;integrated security=sspi</connectionString>
<!-- commands to install database -->
<install-command>
<text>CREATE DATABASE MyLogs</text>
<connectionString>server=.\SQLEXPRESS;database=master;integrated security=sspi</connectionString>
<ignoreFailures>true</ignoreFailures>
</install-command>
<install-command>
<text>
CREATE TABLE LogEntries(
id int primary key not null identity(1,1),
TimeStamp datetime2,
Message nvarchar(max),
level nvarchar(10),
logger nvarchar(128))
</text>
</install-command>
<!-- commands to uninstall database -->
<uninstall-command>
<text>DROP DATABASE MyLogs</text>
<connectionString>server=.\SQLEXPRESS;database=master;integrated security=sspi</connectionString>
<ignoreFailures>true</ignoreFailures>
</uninstall-command>
</target>

Resources