I would like to view in a web browser the content of the H2 database started by Spring thanks to the following configuration:
<jdbc:embedded-database id="dataSource" type="H2" />
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="classpath:db/populateDB.sql"/>
</jdbc:initialize-database>
I searched for the JDBC URL in the logs:
DEBUG o.s.j.d.SimpleDriverDataSource - Creating new JDBC Driver Connection to [jdbc:h2:mem:dataSource;DB_CLOSE_DELAY=-1]
So that I could fill the connection form as follows:
But unfortunately, the db is still empty, whereas it shouldn't due to the populateDB.sql script.
Any idea?
Thanks!
Pretty much the same question as View content of H2 or HSQLDB in-memory database.
Simply add the following to your configuration.
<bean id="h2Server" class="org.h2.tools.Server" factory-method="createTcpServer" init-method="start" destroy-method="stop" depends-on="h2WebServer">
<constructor-arg value="-tcp,-tcpAllowOthers,-tcpPort,9092"/>
</bean>
<bean id="h2WebServer" class="org.h2.tools.Server" factory-method="createWebServer" init-method="start" destroy-method="stop">
<constructor-arg value="-web,-webAllowOthers,-webPort,8082"/>
</bean>
This will start both H2 web console and TCP server in the same JVM as your embedded database so that you can access port 8082 with your web browser (enter jdbc:h2:mem:dataSource as URL), or access port 9092 with external SQL client such as SQuirreLSQL and view the same data.
With spring boot you can do this with couple of configurations in the application.properties file.
spring.h2.console.enabled=true
spring.h2.console.path=/console/
Then you can access h2 web console in http://localhost:8080/console/. Default login configuration should work unless you change them.
See spring boot documentation.
The database URL jdbc:h2:mem:dataSource means you are using an in-memory database. Now if you start a second Java process and connect to this database, you will end up having two in-memory databases (one for each process).
If you want to connect to the existing database, you have multiple options:
Connect to the database from within the same process. Don't start a second process.
Use a persisted database, with a hardcoded absolute path, for example: `jdbc:h2:/data/db/dataSource'.
More complicated / not recommended: If you start a second process, you could theoretically connect to an in-memory database using the server mode. But that means you need to start the server where you ran the test.
When using Spring Boot you can register the H2 Console Servlet as follows:
#Bean
public ServletRegistrationBean h2servletRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(new WebServlet());
registration.addUrlMappings("/console/*");
registration.addInitParameter("webAllowOthers", "true");
return registration;
}
If you want the console to be available remotely, the important line is the addInitParameter to set the "webAllowOthers" to "true".
When you use the an embeddeb with the xml jdbc configuration the default name of the database is 'testdb'
Try to use in your url connection:
jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
For those wanting a Java Config setup it's fairly easy to do as well initializing the TCP server when implementing ServletContextInitializer and chaining the Console Server...
#Configuration
public class WebConfig implements ServletContextInitializer{
...
#Override
public void onStartup( ServletContext servletContext )
//do stuff onStartUp...
initH2TCPServer( servletContext );
....
#Bean(initMethod="start", destroyMethod="stop")
public Server initH2TCPServer(ServletContext servletContext) {
log.debug( "Initializing H2 TCP Server" );
try {
server = Server.createTcpServer( "-tcp", "-tcpAllowOthers", "-tcpPort", "9092" );
} catch( SQLException e ) {
e.printStackTrace();
} finally {
//Always return the H2Console...
initH2Console( servletContext );
}
return server;
}
public void initH2Console( ServletContext servletContext ) {
log.debug( "Initializing H2 console" );
ServletRegistration.Dynamic h2ConsoleServlet = servletContext.addServlet(
"H2Console", new org.h2.server.web.WebServlet() );
h2ConsoleServlet.addMapping( "/console/*" );
);
}
I was facing similar issue. But the fix was really very small. Please refer page : https://springframework.guru/using-the-h2-database-console-in-spring-boot-with-spring-security/ for more details.
In my case, I have added scope of H2 dependency as "runtime". I removed it and it fixed my issue. Not I am able to see tables in H2-console.
Previous dependency in my pom was :
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
And new dependency which fixed my issue :
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
Related
I already have an existing application with hibernate and embedded derby working.
My hibernate.cfg.xml has the following settings
<property name="connection.driver_class">org.apache.derby.jdbc.EmbeddedDriver</property>
<property name="connection.url">jdbc:derby:data;create=true</property>
<property name="connection.username">application</property>
<property name="connection.password">password</property>
<property name="hibernate.default_schema">my_application</property>
everything has been working fine but I wish to add spring boot to that project and I am getting
Failed to create sessionFactory
object.org.hibernate.service.spi.ServiceException: Unable to create
requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
when I am loading the sessionFactory from hibernate. Why can I not do that? Is loading embedded Derby from spring boot the only way? I don't want spring boot to have any relation to the database.
Also, after adding spring boot my log4j.properties file is not read anymore even if I do not run spring boot at all.
Found it. needed to set application.properties like this
spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.DerbyDialect
spring.datasource.url=jdbc:derby:data;create=true
spring.datasource.username=application
spring.datasource.password=password
spring.datasource.driver-class-name=org.apache.derby.jdbc.EmbeddedDriver
spring.datasource.initialize=true
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
my boot app needs a hibernate bean like this
#SpringBootApplication
#EntityScan("core.peristence.dtos")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
#Bean
public HibernateJpaSessionFactoryBean sessionFactory() {
return new HibernateJpaSessionFactoryBean();
}
}
and my service can autowire the sessionFactory now like this:
#Service
public class MyService {
#Autowired
private SessionFactory sessionFactory;
...
}
I been searching again for this issue where I cannot locate the jndi database by using java config. Before this I use xml and its work perfectly but in java config it cause an issue;
Xml code:
<!-- Jndi database connection -->
<jee:jndi-lookup id="dbDataSource" jndi-name="${db.jndi}"
resource-ref="true" />
<beans:bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate" >
<beans:property name="dataSource" ref="dbDataSource"></beans:property>
</beans:bean>
Java config now:
#Bean(name = "dbDataSource")
public DataSource dataSource(#Value("${db.jndi}") String jndiName)
{
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(jndiName);
}
#Bean
public JdbcTemplate jdbcTemplate(DataSource ds) {
return new JdbcTemplate(ds);
}
Properties file:
db.jndi=jndi/myData
JNDI name in weblogic:
jndi/myData
After change to java config, sometimes the system can read the database but rarely occur, until I clean and restart my computer then it can find the database, but usually its always trigger:
javax.naming.NameNotFoundException: Unable to resolve 'jndi.myData'. Resolved 'jndi'; remaining name 'myData'
Why the application cannot find the database correctly?
Thanks!!!
I've had the same issue. If you're using 4.x version of spring that's probably the cause.
You should also check Weblogic's JNDI Tree. If your data source disapears from the tree after rebuilding the project, that's another symptom
If that's the case, what's happening is:
Your Datasource implements Closeable (and therefore AutoCloseable) and the context will always invoke the shutdown method regardless of your Bean definition
as seen here : SPR-12551: Document how to prevent a JNDI DataSource retrieved using JavaConfig to be removed on shutdown of the context
It's been marked as a documentation issue as this is the "expected" behaviour:
This issue was solely about documentation since we decided not to implement anything at the framework level
the solution, is to define the destroy method of the bean as empty, such as:
#Bean(name = "dbDataSource", destroyMethod="")
public DataSource dataSource(#Value("${db.jndi}") String jndiName)
{
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(jndiName);
}
#Bean
public JdbcTemplate jdbcTemplate(DataSource ds) {
return new JdbcTemplate(ds);
}
This is described in this issue (SPR-13022:Destroy callback cannot be disabled for AutoCloseable beans) .
PS: By the way, it seems like on early 4.x version of spring you couldn't override this behaviour by assingning destroyMethod. It apears that this bug was fixed on version 4.2 RC1.
I've had the same issue and I solved problem. I used to jndi datasource on weblogic. After I restart application, I notice my jndi datasource remove from Weblogic's JNDI Tree. Xml configuration works successfuly but java configuration don't work.
My old spring version: 4.1.6.RELEASE Upgrade to 4.3.9.RELEASE
Xml configuration like this;
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>${db-jndi.name}</value>
</property>
</bean>
Java configuration like this;
#Bean(name = "dataSource")
public DataSource dataSource() throws IllegalArgumentException, NamingException
{
JndiTemplate jndiTemplate = new JndiTemplate();
DataSource dataSource = (DataSource) jndiTemplate.lookup(env.getProperty("db-jndi.name"));
logger.info("DataSource initialized in jndi ");
return dataSource;
}
Then i changed
#Bean(name = "dataSource")
to
#Bean(name = "dataSource", destroyMethod = "")
And it's works successfuly.
It looks like your datasource hasn't been deployed. You should look for JNDI tree for the server you tried to deploy datasource. (https://docs.oracle.com/cd/E12839_01/apirefs.1111/e13952/taskhelp/jndi/ViewObjectsInTheJNDITree.html) If you don't see "jndi.myData" on JNDI tree, you can assume that your datasource haven't been deployed. So you can go to your datasource monitoring tab and test the datasource. (https://docs.oracle.com/cd/E17904_01/apirefs.1111/e13952/taskhelp/jdbc/jdbc_datasources/TestDataSources.html)
I would like to use HikariCP from the Spring Cloud Connectors. I am not sure how to proceed...
I have updated my Spring Cloud Connectors to 1.2.0.RC1.
Here is my current config:
#Configuration
#Profile({ Profiles.CLOUD })
public class CloudDataSourceConfiguration extends AbstractCloudConfig {
#Bean
public DataSource dataSource() {
int dbcpMaxActive = 10;
int dbcpMaxWait = 200;
PoolConfig poolConfig = new PoolConfig(dbcpMaxActive, dbcpMaxWait);
ConnectionConfig connectionConfig = new ConnectionConfig("sessionVariables=sql_mode='ANSI';characterEncoding=UTF-8");
DataSourceConfig serviceConfig = new DataSourceConfig(poolConfig, connectionConfig);
return connectionFactory().dataSource("CLEARDB_DATABASE", serviceConfig);
}
}
Can someone please advise?
edit: When I start the app with the cloud profile, I can read
2015-05-23 22:46:56,029 [localhost-startStop-1] INFO org.springframework.cloud.service.relational.PooledDataSourceCreator - Found Tomcat high-performance connection pool on the classpath. Using it for DataSource connection pooling.
from the log output.
edit 2: HikariCP is in the classpath and it seems that tomcat high performance connection pool is also in the classpath.
As stated in my second edit, both tomcat jdbc & HikariCP were on the classpath. By removing tomcat jdbc as follows (in my gradle script):
compile("org.springframework.boot:spring-boot-starter-data-jpa"){
exclude group: 'org.apache.tomcat', module: 'tomcat-jdbc'
}
only HikariCP remained on the classpath and it was picked up properly as shown by the log output below:
INFO org.springframework.cloud.service.relational.PooledDataSourceCreator - Found HikariCP on the classpath. Using it for DataSource connection pooling.
In a redis java client,I found this:
To use it, init a pool:
JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");
You can store the pool somewhere statically, it is thread-safe.
I just wondering,with spring,how can I store JedisPool statically.
You don't.
In spring it's preferable to define a JedisPool bean and autowire it wherever necessary.
For example, using xml config:
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg>
<bean class="redis.clients.jedis.JedisPoolConfig" />
</consrtuctor-arg>
<constructor-arg value="localhost" />
</bean>
and then, inside your beans:
#Autowire
JedisPool jedisPool;
It's even simpler if you use spring java config - you can use exactly the code you posted to define the pool bean:
#Configuration
public class Configuration {
#Bean
public JedisPool createJedisPool() {
return new JedisPool(new JedisPoolConfig(), "localhost");
}
}
Also you might want to take a look at spring-data - redis
I've been struggling with a configuration which requires a knowledge in AOP.
i must admit that AOP is that part i'm trying to get for a while without success.
It seems that my shiro annotations are not scanned and thus are ignored.
i've tried using shiro 1.1.0+ maven3+spring 3.0.5.RELEASE, hibernate 3.6.1.Final with ZK 5.0.6.
i got my hibernaterealm working , talking to database, i got the authentication working, i successfully(i believe) get the roles and permission loaded.
so to test the authorization side i have somewhere in my code this :
Subject currentUser = SecurityUtils.getSubject();
if (!currentUser.isPermitted("businessaccount:list")) {
throw new AuthorizationException("User not authorized");
}
and it works fine.
So i know my permissions were loaded.i'll be convenient for me using annotations to i've put it in implementation class, because i didn't plan on using interface at first place with my controller classes which are extending ZK GenericForwardController.
i've seen this bug and i've decided to do a try with one interface with the #RequiresPersmissions on methods.
apparently it's still not working as in it's giving access to unauthorized subject.there is no error in my log.Maybe i'm doing something wrong here are snippet of the codes:
#Component("layouteventhandler")
public class LayoutEventHandlerImpl extends GenericForwardComposer implements LayoutEventHandler {
Logger logger = Logger.getLogger(LayoutEventHandlerImpl.class);
Menuitem logout;
//...
#Override
public void onClick$pAccounts() {
try {
execution.sendRedirect("/accounts/personal/list");
} catch (Exception ex) {
logger.info("Error redirecting to personal accounts", ex);
}
}
#Override
public void onClick$bAccounts() {
try {
execution.sendRedirect("/accounts/business/list");
} catch (Exception ex) {
logger.info("Error redirecting to business accounts", ex);
}
}
//.....
}
its interface it :
public interface LayoutEventHandler {
#RequiresPermissions(value="personalaccount:list")
public void onClick$pAccounts();
#RequiresPermissions(value="businessaccount:list")
public void onClick$bAccounts();
//.....
}
here is my shiro applicationcontext
<bean id="hibernateRealm" class="com.personal.project.admin.webapp.security.DatabaseRealm" />
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="hibernateRealm" />
</bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<!-- <property name="proxyTargetClass" value="true" />-->
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
<!-- Secure Spring remoting: Ensure any Spring Remoting method invocations can be associated
with a Subject for security checks. -->
<bean id="secureRemoteInvocationExecutor" class="org.apache.shiro.spring.remoting.SecureRemoteInvocationExecutor">
<property name="securityManager" ref="securityManager"/>
</bean>
<!-- ... -->
is it in there something that i should do? thanks for reading and helping out
I don't know Shiro, but I'm guessing that you've put annotations on your bean classes which implement interfaces and then you're proxying them for security, transactions, and/or something else. When that happens, the object that's returned is a JDK dynamic proxy, which isn't an instance of your bean's concrete class, only of the interface it implements. Therefore any annotation scanning that depends on annotations in the concrete class won't find them.
To expand on Ryan Stewart's answer, you need to add
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
to the implementing class (not the interface) and move the Shiro annotations to it.
I encountered a similar problem when I was running two spring contexts. There is a parent root context that defined Database, Service, Security and non-SpringMVC web beans and a child web context for a Spring MVC REST api which contained the Controllers I want to proxy. The Configuration for each context was class path scanning separate packages.
In this case make sure that the DefaultAdvisorAutoProxyCreator and the AuthorizationAttributeSourceAdvisor beans that are requied are defined in the child web context (i.e. where the Rest Controllers are class path scanned) as defining them in the parent context does not work (the documentation on the DefaultAdvisorAutoProxyCreate is quite clear about this in hindsight!).
Posting this in case someone else encounters the same issue.