I have a #repository class where I am using :
#Autowired
private NamedParameterJdbcTemplate template;
and defining datasource in application.properties. However, when method runs it thrown null pointer exception on line
template.update(INSERT_SQL_USER, parameters);
saying template is run. shouldn't springboot automatically bind datasource with the template? how can I resolve this issue?
p.s. I am using MySQL database
thanks in advance.
Related
Maybe I'm on the wrong course or totally misunderstanding something.
I've merged a Citrus IntegrationTest from Junit4Runner to Junit5 (with CitrusExtension).
There is an EndpointConfiguration class
#Configuration
#PropertySource("test-setup.properties")
#PropertySource("service-paths.properties")
public class RestEndpointConfig {
#Value("${testenv.host}") //defined in test-setup.properties
private String host;
...
}
And a TestClass
#ExtendWith(CitrusExtension.class)
#RunWith(JUnitPlatform.class)
public class BaseIT{
#CitrusEndpoint
protected HttpClient httpClient;
#Value("${rest.session}") //defined in service-paths.properties
private String sessionPath;
}
In the test class I want to access values defined in the service-paths.properties file.
This worked with JUnit4 but after the changes to JUnit5 it seems that the properties are no longer available in a 'global' context.
Turning the log level to 'debug' shows, that the properties file is loaded.
So my question is: What do I need to change in order to get access to the service-paths properies in my IT classes. What am I missing, what is best practice in this case?
Thanks in advance for any feedback.
Property value resolving via #Value annotation is a core Spring framework feature. So you need to add SpringExtension to your JUnit5 test. You can do this in addition to using the CitrusExtension.
I'm doing my first steps with Camel and currently working on writing a simple junit test using jms as a transport.
Here is a code I wrote:
public class FirstMockTest extends CamelTestSupport {
#Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from("jms:topic:quote")
.to("mock:quote");
}
};
}
#Test
public void testMessageCount() throws InterruptedException {
MockEndpoint mockEndpoint = getMockEndpoint("mock:quote");
mockEndpoint.setExpectedMessageCount(1);
template.sendBody("jms:topic:quote", "Camel rocks");
mockEndpoint.assertIsSatisfied();
}
}
Because of missing connectionFactory I got the following exception:
org.apache.camel.FailedToCreateRouteException: Failed to create route route1: Route(route1)[[From[jms:topic:quote]] -> [To[mock:quote]]] because of connectionFactory must be specified
I'm able to fix it adding the following lines to my route:
ConnectionFactory connectionFactory =
new ActiveMQConnectionFactory("vm://localhost?roker.persistent=false");
context.addComponent("jms", JmsComponent.jmsComponent(connectionFactory));
But I don't like I'm adding some components to my context inside the route. Also, If i want to have another route I will need to do it again.
Obviously, there should be another way to tell my test about connection factory.
Thank you in advance!
It's a good idea to define the JMS connection factory outside of your Camel context and, if possible, reuse it. How to do that depends on your component model / execution environment.
If you're using a Java SE version that supports CDI, that would be an obvious choice. You'd define your JMS connection factory as a named component once and inject it everywhere you need it. Have a look at http://camel.apache.org/cdi.html and for testing support at http://camel.apache.org/cdi-testing.html
If you're using Spring, define your connection factory as a spring bean and inject it wherever you need it.
If you're using Java EE on an application server, you'd usually define the JMS connection factory using the mechanisms of that app server. You'd then look up the JMS connection factory using JNDI.
If you're running in an OSGi container, you should define the JMS connection factory in its own bundle and export it as an OSGi service. In the bundle of your Camel context, import that OSGi servide and inject it into the Camel context.
In all above cases you should consider using a pooled JMS connection factory.
For CDI, Spring and OSGi, have a look at: http://activemq.apache.org/maven/5.14.5/apidocs/org/apache/activemq/jms/pool/PooledConnectionFactory.html
For Java EE the way how to set pooling parameters depends on your app server.
Note of caution: for Java SE CDI and Spring there should be only one Camel context per application (you can have many routes, though). So if the JMS connection factory is only used in that one Camel context, there is not much reuse. Despite that I still think it's preferable to define the JMS connection outside of the Camel context in a separate component. It's, well, cleaner.
Since you are writing a junit you can avoid creating a ConnectionFactory if you stub the jms endpoint. You can name the endpoint as stub:jms:topic:quote. Have a look at sample example at link https://github.com/camelinaction/camelinaction2/blob/master/chapter9/mock/src/test/java/camelinaction/FirstMockTest.java
I am need to unmock a static method & call the real method in the class constructor as this will give connection to the DB. Now using powermock when I say #RunWith(PowerMockRunner.class) it doesnt allow me to call the real method. This was possible in mockito but I need to use powermock as I need to mock other static methods too.
public TestESMock() throws ConfigurationException{
DatabaseImpl dbImpl=DatabaseImpl.newDatabaseImpl(null);
}
Can someone tell me how to I do this.
There was no problem with powermockito. I was getting exception as powermockito 1.5.6 was not able to connect with SQL Server JDBC4
Castle Windsor 3.2 provides a cool addition that is Diagnostic logging in the container. This helped me redirect the container logs to a log4net log file that's being used to store the application logs.
What I'd like to do now is to be able to actually catch the Exception the container detects while injecting my optional property.
In my specific situation, an Oracle database error ORA-28000: the account is locked was being raised while Castle tried to execute my code to inject the Database property in a BaseController class:
public class BaseController : Controller
{
/// <summary>
/// Repository interface injected by Castle Windsor IoC container.
/// See <see cref="MyProject.Widgets.CastleWindsor.Facilities.PersistenceFacility.Init()"/> for more information.
/// </summary>
public ILogRepository Database { get; set; }
}
This Database property is null when I'm inside an action method in an Controller that inherits from BaseController. This all happens because Castle Windsor "swallows" the exception. The only message the user gets is: Object reference not set to an instance of an object. OK but I'd like to show the real exception/reason to the user, that is, ORA-28000: the account is locked. This message gets logged by Castle Windsor thanks to the aforementioned Diagnostic logging. This is cool but I want to be able to really catch the exception inside the catch block:
public class SubCatListController : BaseController
{
public ActionResult SubCatList(string subcat)
{
try
{
var sub = Database.GetLogSubCategory(subcat);
}
catch(Exception e) // I'd like to get the real exception from Castle Windsor here...
{
Logger.Error(e.Message, e);
}
}
}
Is this scenario possible with property injection?
As Krzysztof Kozmic mentioned in his comment we should not have any code that tries to do external object initialization while injecting a property.
My problem as I describe in this subsequent comment was that I was trying to open a database connection while initializing the property.
I removed that code and now the exception is only raised in my own domain code when that injected property is used for the 1st time.
Today I hit this same problem: one thing that helped me figure out the error was to momentarily use Constructor injection instead, like this:
private OEVizion _database;
public ReportingPeriodsController(OEVizion database)
{
_database = database;
}
Doing this I was able to see what was the error: version mismatch between log4net - the one in the OEVizion class library and the one used in the .Web project.
After getting the EF context correctly initialized I got back to Property injection and I'm back in business. :D
When you have optional dependencies it is always better to use the Null Object pattern.
public BaseController() {
Database = NullLogRepository.Instance;
}
It prevent the NullReferenceException and you can provide behavior you expect (do nothing, throw specific exception, log to trace etc.)
I have a Spring MVC app that is running fine on local tomcat etc. Its a Spring 3.1 MVC/Hibernate app.
I am using (where possible) pure Java #Configuration for the app - and I am now trying to deploy the app to CloudFoundry (via STS), but I am struggling to get the MySql db configured (from memory, with xml config you dont need to do anything and Spring/CloudFoundry auto-injects the required user/password etc, but its been a while since I deployed anything to CF).
I have tried both of the following configurations:
#Bean
public BasicDataSource dataSource() throws PropertyVetoException {
//CloudFoundry config
final CloudEnvironment cloudEnvironment = new CloudEnvironment();
final List<MysqlServiceInfo> mysqlServices = cloudEnvironment.getServiceInfos(MysqlServiceInfo.class);
final MysqlServiceInfo serviceInfo = mysqlServices.get(0);
BasicDataSource bean = new BasicDataSource();
bean.setDriverClassName("com.mysql.jdbc.Driver");
bean.setUrl(serviceInfo.getUrl());
bean.setUsername(serviceInfo.getUserName());
bean.setPassword(serviceInfo.getPassword());
return bean;
}
The above failed on out of bounds on the .get(0) line of the mysqlServices. This was based on the answer suggested here.
I also tried leaving the datasource as what it runs on as local to see if the properties just get injected, but no luck there either. (the below was tried with the values as per the Spring sample code here, and also using property placeholders from my db.connection props file)
#Bean
public BasicDataSource dataSource() throws PropertyVetoException {
BasicDataSource bean = new BasicDataSource();
bean.setDriverClassName("com.mysql.jdbc.Driver");
bean.setUrl("");
bean.setUsername("spring");
bean.setPassword("spring");
return bean;
}
Edit
I have also used the getServiceInfo(String, Class) method passing in the name of the MySql service that I have created and bound to the application, but that just NPEs similar to the getServiceInfos(..) approach
Ok, this was just a stupid mistake - when I deployed the app via STS I had selected Java Web app rather than the "Spring" type. Not sure why that would make the CloudEnvironment properties not be available (I was under the impression that approach was the common method to inject the details in non-Spring apps) - but re-deploying it to the server as a Spring app resolved the probs!