In my Spring mvc application, calling following method , when click 'Save' button in jsp page.
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String addUser(#ModelAttribute("user") #Valid User u,
BindingResult result, #ModelAttribute("category") UserCategory uc,
BindingResult resultCat, Model model, RedirectAttributes reDctModel) {
this.userService.addUser(u); // adding new user to DB
reDctModel.addFlashAttribute("msgSucess","Successfully saved..!");
this.sendEmail(u.getUsr_email(),"RDMS","Login Details"); // For sending mail
return "redirect:/users";
}
public String sendEmail(String recipientAddress,String subject,String message) {
// creates a simple e-mail object
SimpleMailMessage email = new SimpleMailMessage();
email.setTo(recipientAddress);
email.setSubject(subject);
email.setText(message);
// sends the e-mail
this.mailSender.send(email);
return "Result";
}
This is my applicationcontext
</bean>
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com" />
<property name="port" value="587" />
<property name="username" value="myemailaddress#gmail.com" />
<property name="password" value="********" />
<property name="javaMailProperties">
<props>
<prop key="mail.transport.protocol">smtp</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
</props>
</property>
</bean>
The issue is, after adding sendEmail() ,it takes around 15 seconds to save the new record.Before adding this method it takes only 1 second.Can anybody guide me to reducing slowness of the programme or calling sendEmail() after finishing first transaction.Thanks in advance.
You have to create async service and configure your application for asynchronous usage, here you have spring tutorial. In async service you have to place your code for sending email. Below you can see sample code for 2 classes first is service second is application class,
import java.util.concurrent.Future;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
#Service
public class SampleService {
#Async
public Future sendEmail(String email) {
// here you can place your code for sending email
return new AsyncResult("email sent successful");
}
}
import java.util.concurrent.Future;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
#SpringBootApplication
#EnableAsync
public class Application implements CommandLineRunner {
#Autowired
SampleService sampleService;
#Override
public void run(String... args) throws Exception {
Future page1 = sampleService.sendEmail("test#gmail.com");
while (!page1.isDone()) {
Thread.sleep(10);
}
System.out.println(page1.get());
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Related
I am building a web application using spring MVC which is connected to the database. This is part of my bean config file.
<!-- Define Database DataSource / connection pool -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/java_task?useSSL=false" />
<property name="user" value="me" />
<property name="password" value="me" />
<!-- these are connection pool properties for C3P0 -->
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<property name="maxIdleTime" value="30000" />
</bean>
<!-- Define Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="packagesToScan" value="com.javatask.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
As you can see my data source is defined in a hard way. In code I am using #Autowired annotation to inject sessionFactory. But I would like to inject sessionFactory (jdbc, username, password etc.) with data which I will obtain from user during run time. For example he will write me those data to the textfeild and then I will create sessionFactory (based on his data) which will be connected to his database.
I was looking for an answer but unluckily I have not found anything that would fit to this problem.
There are multiple ways that spring bean definition can be changed in run time. One way is to refresh the Spring Application Context in run time which would have the bean definition specific to the functionality rather than all bean definition.
((ConfigurableApplicationContext)applicationContext).refresh();
Let me explain using one simple use case:
Create a PropertyBean which will load value from external properties file.
Create PropertiesApplicationContext which would have only PropertyBean definition config rather than all beans belongs the application.
Use ConfigurableApplicationContext refresh() method to reload ProperiesBean definition in run time.
More details about below example code snippet:
Web Application should display a Property Value from a bean which
will read the value from a external property file.
Property value will change anytime in external properties file.
Web Application should not restarted.
Here, bean definition should be changed in run time.
Spring Boot Application Code:
#SpringBootApplication(scanBasePackages = {"vijay.controller","vijay.configuration"})
public class SpringContextRefreshApplication extends SpringBootServletInitializer{
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SpringContextRefreshApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SpringContextRefreshApplication.class, args);
}
}
MVC Configuration:
package vijay.configuration;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
/**
* MVC Configuration
* #author Vijay
*/
#Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter{
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/view/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
registry.viewResolver(resolver);
}
}
Custom (Property) Application Context Aware:
package vijay.configuration;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* PropertyApplicationContext Class to load Property Configuration XML.
* #author Vijay
*/
public class PropertyApplicationContext implements ApplicationContextAware{
private ApplicationContext applicationContext;
private static PropertyApplicationContext propertyApplicationContext;
private PropertyApplicationContext(){
applicationContext = new ClassPathXmlApplicationContext("property-config.xml");
}
#Override
public void setApplicationContext(ApplicationContext ac) throws BeansException {
if(applicationContext == null){
this.applicationContext = ac;
}
}
public ApplicationContext getApplicationContext(){
return applicationContext;
}
public static PropertyApplicationContext getInstance(){
if(propertyApplicationContext == null){
propertyApplicationContext = new PropertyApplicationContext();
}
return propertyApplicationContext;
}
}
MVC Controller:
package vijay.controller;
import vijay.beans.PropertyDto;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import vijay.configuration.PropertyApplicationContext;
/**
* Property List Controller.
* #author Vijay
*/
#Controller
public class PropertyController {
#RequestMapping("/")
public String testController(){
System.out.println("vijay.controller.PropertyController.testController()");
return "sample";
}
#RequestMapping(path = "/getProperties")
public String testPropertiesController(ModelMap modelMap){
ApplicationContext applicationContext = PropertyApplicationContext.getInstance().getApplicationContext();
PropertyDto propertyDto = (PropertyDto) applicationContext.getBean("propertyBean");
System.out.println("vijay.controller.PropertyController.testPropertiesController() " + propertyDto);
modelMap.addAttribute("message", propertyDto.getKey());
return "sample";
}
/**
* Method will refresh ApplicationContext
* #param modelMap as ModelMap
* #return viewName as String
*/
#RequestMapping(path = "/refreshProperties")
public String refreshBean(ModelMap modelMap){
ApplicationContext applicationContext = PropertyApplicationContext.getInstance().getApplicationContext();
// Refresh Application Context
((ConfigurableApplicationContext)applicationContext).refresh();
PropertyDto propertyDto = (PropertyDto) applicationContext.getBean("propertyBean");
System.out.println("vijay.controller.PropertyController.refreshBean()" + propertyDto);
modelMap.addAttribute("message", propertyDto.getKey());
return "sample";
}
}
Spring Bean (Property-config.xml) definition File:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" >
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file:C://sample.properties" />
</bean>
<context:annotation-config/>
<context:component-scan base-package="vijay.beans"/>
</beans>
View JSP (sample.jsp):
<!DOCTYPE html>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html lang="en">
<body>
<div>
<div>
<h1>Spring Boot JSP Example</h1>
<h2>Property Value :: ${message} !</h2>
</div>
</div>
</body>
</html>
Here, MVC Controller has /refreshProperties which will refresh the PropertiesBean defined in PropertiesApplicationContext. As properties-config.xml the only bean definition defined in PropertiesApplicationContext, propertiesBean alone will be refreshed and no other bean definition will be refreshed.
Similar way, you can create Application Context by extending ApplicationContextAware which will have bean definition of sessionFactory. You can get SessionFactory wherever required from this context and refresh the context wherever required.
This is one way to achieve the bean definition change in run time.
Did you try this [Change SessionFactory datasource jdbcurl late in runtime] (Change SessionFactory datasource jdbcurl late in runtime)?
I am new in spring MVC i have got an issue while send email through spring . no exception will occur but mail not send.
my applicationContext.xml
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com" />
<property name="username" value="uname" />
<property name="password" value="pass" />
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.socketFactory.port">465</prop>
<prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
<prop key="mail.smtp.port">465</prop>
</props>
</property>
</bean>
my controller class
#Controller
public class WebController {
// System.out.println("suceees");
#Autowired
private JavaMailSender mailSender;
#RequestMapping(value = "/index", method = RequestMethod.GET)
public String index() {
return "index";
}
#RequestMapping(value = "/redirect", method = RequestMethod.GET)
public String redirect() {
sendMail();
return "redirect:finalPage";
}
#RequestMapping(value = "/finalPage", method = RequestMethod.GET)
public String finalPage() {
return "final";
}
public void sendMail() {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom("sender");
helper.setTo("receiver");
helper.setSubject("hi");
helper.setText("welcome");
// attach the file
FileSystemResource file = new FileSystemResource(new File("/home/ajmal/Pictures/messi.jpg"));
helper.addAttachment("messi.jpg", file);//image will be sent by this name
mailSender.send(message);
} catch (MailException | MessagingException ex) {
System.err.println("error");
}
}
}
thanks in advance .. no exception will occur. but mail not send ?
We had into the same problem sometime back, with Spring Boot 1.2.5. Looks like with the latest version of Java Mail, now another property is needed - spring.mail.properties.mail.smtp.ssl.enable to be set as true. See this post for details.
Also, when I tested my application, I saw that merely giving the regular gmail password didn't anymore work. I needed a 2-step verified account, and had to use an application password.
I am trying to get my Spring rest controller to return jsonp but I am having no joy
The exact same code works ok if I want to return json but I have a requirement to return jsonp
I have added in a converter I found source code for online for performing the jsonp conversion
I am using Spring version 4.1.1.RELEASE and Java 7
Any help is greatly appreciated
Here is the code in question
mvc-dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="true" />
<property name="parameterName" value="mediaType" />
<property name="ignoreAcceptHeader" value="false"/>
<property name="useJaf" value="false"/>
<property name="defaultContentType" value="application/json" />
<property name="mediaTypes">
<map>
<entry key="atom" value="application/atom+xml" />
<entry key="html" value="text/html" />
<entry key="jsonp" value="application/javascript" />
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml"/>
</map>
</property>
</bean>
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="contentNegotiationManager" ref="contentNegotiationManager" />
<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/templates/slim/${views.template.directory}/" />
<property name="suffix" value=".jsp" />
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="com.webapp.handler.MappingJacksonJsonpView" />
</list>
</property>
</bean>
</beans>
com.webapp.handler.MappingJacksonJsonpView
package com.webapp.handler;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
public class MappingJacksonJsonpView extends MappingJackson2JsonView {
/** Local log variable. **/
private static final Logger LOG = LoggerFactory.getLogger(MappingJacksonJsonpView.class);
/**
* Default content type. Overridable as bean property.
*/
public static final String DEFAULT_CONTENT_TYPE = "application/javascript";
#Override
public String getContentType() {
return DEFAULT_CONTENT_TYPE;
}
/**
* Prepares the view given the specified model, merging it with static
* attributes and a RequestContext attribute, if necessary.
* Delegates to renderMergedOutputModel for the actual rendering.
* #see #renderMergedOutputModel
*/
#Override
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
LOG.info("Entered render Method :{}", request.getMethod());
if("GET".equals(request.getMethod().toUpperCase())) {
LOG.info("Request Method is a GET call");
Map<String, String[]> params = request.getParameterMap();
if(params.containsKey("callback")) {
String callbackParam = params.get("callback")[0];
LOG.info("callbackParam:{}", callbackParam);
response.getOutputStream().write(new String(callbackParam + "(").getBytes());
super.render(model, request, response);
response.getOutputStream().write(new String(");").getBytes());
response.setContentType(DEFAULT_CONTENT_TYPE);
}
else {
LOG.info("Callback Param not contained in request");
super.render(model, request, response);
}
}
else {
LOG.info("Request Method is NOT a GET call");
super.render(model, request, response);
}
}
}
Controller Method In Question
#RequestMapping(value = { "/sources"}, method = RequestMethod.GET,
produces={MediaType.ALL_VALUE,
"text/javascript",
"application/javascript",
"application/ecmascript",
"application/x-ecmascript",
"application/x-javascript",
MediaType.APPLICATION_JSON_VALUE})
#ResponseBody
public Object getSources(#PathVariable(value = API_KEY) String apiKey,
#RequestParam(value = "searchTerm", required = true) String searchTerm,
#RequestParam(value = "callBack", required = false) String callBack) {
LOG.info("Entered getSources - searchTerm:{}, callBack:{} ", searchTerm, callBack);
List<SearchVO> searchVOList = myServices.findSources(searchTerm);
if (CollectionUtils.isEmpty(searchVOList)) {
LOG.error("No results exist for the searchterm of {}", searchTerm);
return searchVOList;
}
LOG.debug("{} result(s) exist for the searchterm of {}", searchVOList.size(), searchTerm);
LOG.info("Exiting getSources");
return searchVOList;
}
**Jquery Ajax Code **
$.ajax({
type: "GET",
url: "http://localhost:8080/my-web/rest/sources,
data: {
"searchTerm": request.term
},
//contentType: "application/json; charset=utf-8",
//dataType: "json",
contentType: "application/javascript",
dataType: "jsonp",
success: function(data) {
alert("success");
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("Failure");
}
});
A snippet of the error stacktrace that I get is as follows
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:168) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:101) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:198) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71) ~[spring-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620) [servlet-api.jar:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) [servlet-api.jar:na]
As stated on the spring.io blog regarding the Spring 4.1 release:
JSONP is now supported with Jackson. For response body methods declare
an #ControllerAdvice as shown below. For View-based rendering simply
configure the JSONP query parameter name(s) on
MappingJackson2JsonView.
#ControllerAdvice
private static class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice() {
super("callback");
}
}
[...] In 4.1 an #ControllerAdvice can also implement
ResponseBodyAdvice in which case it will be called after the
controller method returns but before the response is written and
therefore committed. This has a number of useful applications with
#JsonView the JSONP already serving as two examples built on it.
Javadoc taken from MappingJackson2JsonView:
Set JSONP request parameter names. Each time a request has one of those
parameters, the resulting JSON will be wrapped into a function named as
specified by the JSONP request parameter value.
The parameter names configured by default are "jsonp" and "callback".
You don't need to implement this stuff by yourself. Just reuse the bits from the Spring Framework.
Spring Boot example
Following simple Spring Boot application demonstrates use of build in JSONP support in Spring MVC 4.1.
Example requires at least Spring Boot 1.2.0.RC1.
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;
import java.util.Collections;
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
#RestController
#SpringBootApplication
class Application {
#JsonAutoDetect(fieldVisibility = ANY)
static class MyBean {
String attr = "demo";
}
#ControllerAdvice
static class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice() {
super("callback");
}
}
#Bean
public HttpMessageConverters customConverters() {
return new HttpMessageConverters(false, Collections.<HttpMessageConverter<?> >singleton(new MappingJackson2HttpMessageConverter()));
}
#RequestMapping
MyBean demo() {
return new MyBean();
}
#RequestMapping(produces = APPLICATION_JSON_VALUE)
String demo2() {
return "demo2";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
URL http://localhost:8080/demo?callback=test converts a POJO into a JSONP response:
test({"attr":"demo"});
URL http://localhost:8080/demo2?callback=test converts a String into a JSONP response:
test("demo2");
i am importing data from file ,its get the data suceessfully .my flow to call the ruleimplservice from the main class ,where i get the value from file.bt when i call jdbclogdatarepository to save the data ,it shows the following error.the data isreached successfully in impl bt not in jdbc class.
ERRORS
java.lang.NullPointerException
at com.heavymeddlellc.heavymeddle.metrics.service.RuleServiceImpl.insertlogcontent(RuleServiceImpl.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at $Proxy6.insertlogcontent(Unknown Source)
at com.heavymeddlellc.heavymeddle.utils.readingdata.main(readingdata.java:97)
Java code is as below:
package com.heavymeddlellc.heavymeddle.utils;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.test.context.ContextConfiguration;
import com.heavymeddlellc.heavymeddle.metrics.domain.LogData;
import com.heavymeddlellc.heavymeddle.metrics.repository.jdbc.JdbcLogDataRepository;
import com.heavymeddlellc.heavymeddle.metrics.service.RuleService;
import com.heavymeddlellc.heavymeddle.metrics.service.RuleServiceImpl;
#ContextConfiguration(locations = "/hm-metrics-context.xml")
public class readingdata
{
public static void main(String args[])
{
//RuleService ruleService=new RuleService();
List<LogData> dataList = new ArrayList<LogData>();
Resource r= new ClassPathResource("/hm-metrics-context.xml");
BeanFactory factory=new XmlBeanFactory((org.springframework.core.io.Resource) r);
// LogData logData=(LogData) factory.getBean("ruleService");
RuleService ruleService=(RuleService) factory.getBean("ruleService");
// JdbcLogDataRepository dataRepository= (JdbcLogDataRepository) factory.getBean("ruleService");
LogData logData=new LogData();
// public List<LogData> inserttable(LogData logData2)
//{
try
{
BufferedReader reader=new BufferedReader(new FileReader("E://tracker.log"));
String lines;
String[] contentid;
while((lines=reader.readLine())!=null)
{
String[] datas=lines.split(Pattern.quote("|"));
logData.setUserId(datas[0]);
logData.setRequestDate(datas[1]);
System.out.println(datas[1]);
logData.setSessionId(datas[2]);
System.out.println(datas[2]);
// System.out.println(datas[2]);
contentid=datas[2].split("html/meta/content/");
// System.out.println(contentid[0]);
// System.out.println(datas[2]);
logData.setContentId(contentid[0]);
System.out.println(contentid[0]);
logData.setUserAgent(datas[6]);
System.out.println(datas[6]);
logData.setUserType(datas[4]);
logData.setReferer(datas[5]);
logData.setRedirectUrl(datas[7]);
String sessionId=logData.getSessionId();
System.out.println(logData.getSessionId());
String contentId=logData.getContentId();
System.out.println(contentId);
String userAgent=logData.getUserAgent();
System.out.println(userAgent);
String requestDate=logData.getRequestDate();
String userId=logData.getUserId();
String userType=logData.getUserType();
String referer=logData.getReferer();
String redirectUrl=logData.getRedirectUrl();
//Saystem.out.println(datas[4]);
// dataList.add(logData);
// System.out.print(logData.getSessionId());
//ruleService.insertlogcontent(logData.setSessionId(datas[2]),logData.setContentId(contentid[0]), logData.setRequestDate(datas[1]), logData.setUserId(datas[0]),logData.setUserType(datas[4]),logData.setReferer(datas[5]),logData.setRedirectUrl(datas[7]));
ruleService.insertlogcontent(sessionId, contentId, userAgent, requestDate, userId, userType, referer, redirectUrl);
}
}
catch(Exception e)
{
e.printStackTrace();
}
// return dataList;
// }
}}
/**
*
*/
ruleServiceimpls
package com.heavymeddlellc.heavymeddle.metrics.service;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.*;
import org.springframework.transaction.annotation.Transactional;
import com.heavymeddlellc.heavymeddle.metrics.domain.LogData;
import com.heavymeddlellc.heavymeddle.metrics.repository.LogDataRepository;
#Repository
public class RuleServiceImpl implements RuleService {
private static final Logger log = Logger.getLogger(RuleServiceImpl.class);
#Autowired
private LogDataRepository logDataRepository;
#Override
public void insertlogcontent(String sessionId, String contentId, String userAgent,
String requestDate, String userId,
String userType, String referer,
String redirectUrl) {
//logDataRepository.insertlogcontent(sessionId, contentId,userAgent, requestDate, userId, userType, referer, redirectUrl);
System.out.println(sessionId);
System.out.println(requestDate);
System.out.println(userType);
logDataRepository.insertlogcontent(sessionId, contentId, userAgent,
requestDate, userId, userType, referer, redirectUrl);
}
}
/**
*
*/
package com.heavymeddlellc.heavymeddle.metrics.repository.jdbc;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.heavymeddlellc.heavymeddle.metrics.MetricsException;
import com.heavymeddlellc.heavymeddle.metrics.domain.LogData;
import com.heavymeddlellc.heavymeddle.metrics.repository.LogDataRepository;
import com.heavymeddlellc.heavymeddle.utils.readingdata;
#Transactional
#Repository("logDataRepository")
public class JdbcLogDataRepository implements LogDataRepository {
#Autowired
private JdbcTemplate jdbcTemplate;
#Autowired
private final static String LOG_REDIRECT_VIEW_TABLENAME = "hm_log_redirect_view";
private final static String LOG_REDIRECT_URL_LOOKUP_TABLENAME = "hm_log_redirect_url_lookup";
public final static String LOG_ALL_CONTENTS_VIEW_TABLENAME = "hm_log_all_contents_view";
private final static String LOG_ALL_SN_CONTENTS_VIEW = "hm_log_sn_contents_view";
#Override
public void insertlogcontent(String sessionId, String contentId, String userAgent,
String requestDate, String userId,
String userType, String referer,
String redirectUrl) {
int values=0;
System.out.println(userType);
StringBuffer sqlQuery = new StringBuffer(
"insert into "+JdbcLogDataRepository.LOG_ALL_CONTENTS_VIEW_TABLENAME
+"(uri,content_id,content_owner_id,request_date,user_id,user_type,referer,redirect_url) values (?,?,?,?,?,?,?,?)");
values=jdbcTemplate.update(sqlQuery.toString(),sessionId,contentId,userAgent,requestDate,userId,userType,referer,redirectUrl);
}
}
Spring xml
<!-- Activates scanning of #Autowired -->
<context:annotation-config />
<context:component-scan base-package="com.heavymeddlellc.heavymeddle.metrics" />
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- (this dependency is defined somewhere else) -->
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="metricsProcessor" class="com.heavymeddlellc.heavymeddle.metrics.processor.MetricsProcessorImpl">
<constructor-arg ref="taskExecutor" />
<property name="ruleService" ref="ruleService"/>
</bean>
<bean id="ruleService" scope="prototype" class="com.heavymeddlellc.heavymeddle.metrics.service.RuleServiceImpl">
<!-- This instructs the container to proxy the current bean-->
<aop:scoped-proxy proxy-target-class="false"/>
</bean>
<!-- <bean id="logDataRepository" scope="prototype" class="com.heavymeddlellc.heavymeddle.metrics.repository.JdbcLogDataRepository">
This instructs the container to proxy the current bean
<aop:scoped-proxy proxy-target-class="false"/>
<property name="ruleService" ref="ruleService"></property>
</bean>
-->
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="50" />
<property name="maxPoolSize" value="100" />
<property name="queueCapacity" value="150" />
</bean>
</beans>
Replace the following two lines:
Resource r = new ClassPathResource("/hm-metrics-context.xml");
BeanFactory factory = new XmlBeanFactory((org.springframework.core.io.Resource) r);
with this:
ApplicationContext factory = new ClassPathXmlApplicationContext("/hm-metrics-context.xml");
Read this section of the reference documentation about the differences between a BeanFactory and an ApplicationContext.
Your auto-wiring doesn't work because <context:annotation-config/> is processed as a BeanPostProcessor and the BeanFactory is missing this feature of using BeanPostProcessor extension points, as per the link from the docs above.
We secure our REST services (for server to server communication, no user involved) with Spring Security OAuth2. However when one tries to access a protected resource in a browser, it will show:
<oauth>
<error_description>
An Authentication object was not found in the SecurityContext
</error_description>
<error>unauthorized</error>
</oauth>
We want this to be a custom page of our own choosing. Is there a way?
Setting the access-denied-page won't do. For one it requires the definition of a login page which we don't have as this is a pure server to server communication. For another this attribute is supposedly deprecated since Spring 3.0.. or something.
Anyway.. Debugged my way into the OAuth Error Handling. And found that the response seems to somehow get enriched with the information I see on the error page. Apparently no page rendering at all is done so it looks like there is no error page to replace..?!
At least we want to hide the fact that we use OAuth and just display a basic "Denied" text if we can't have a "real" page.. So maybe I'll have to extend the spring security handler or add a custom filter to modify the response?!
Maybe a redirect to our error page?
Thanks!
Edit
For our current setup check my other SO question here
I had to remove the oauth detail too and my solution was to implement my own OAuth2ExceptionRenderer
package org.some.nice.code;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.ResponseEntity;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.oauth2.provider.error.OAuth2ExceptionRenderer;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
public class HeaderOnlyOAuth2ExceptionRenderer implements OAuth2ExceptionRenderer
{
private final Log logger = LogFactory
.getLog(MyOAuth2ExceptionRenderer.class);
public void handleHttpEntityResponse(HttpEntity<?> responseEntity,
ServletWebRequest webRequest) throws Exception
{
if (responseEntity == null)
{
return;
}
HttpInputMessage inputMessage = createHttpInputMessage(webRequest);
HttpOutputMessage outputMessage = createHttpOutputMessage(webRequest);
logger.info("filtering headers only...");
if (responseEntity instanceof ResponseEntity
&& outputMessage instanceof ServerHttpResponse)
{
((ServerHttpResponse) outputMessage)
.setStatusCode(((ResponseEntity<?>) responseEntity)
.getStatusCode());
}
HttpHeaders entityHeaders = responseEntity.getHeaders();
if (!entityHeaders.isEmpty())
{
outputMessage.getHeaders().putAll(entityHeaders);
}
}
private HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest)
throws Exception
{
HttpServletRequest servletRequest = webRequest
.getNativeRequest(HttpServletRequest.class);
return new ServletServerHttpRequest(servletRequest);
}
private HttpOutputMessage createHttpOutputMessage(
NativeWebRequest webRequest) throws Exception
{
HttpServletResponse servletResponse = (HttpServletResponse) webRequest
.getNativeResponse();
return new ServletServerHttpResponse(servletResponse);
}
}
Then you will have to reference it within your spring context
<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="theRealm" />
<property name="exceptionRenderer" ref="headerOnlyExceptionRender" />
</bean>
<bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="theRealm/client" />
<property name="typeName" value="Basic" />
<property name="exceptionRenderer" ref="headerOnlyExceptionRender" />
</bean>
<bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
<property name="exceptionRenderer" ref="headerOnlyExceptionRender" />
</bean>
<bean id="headerOnlyExceptionRender" class="org.some.nice.code.HeaderOnlyOAuth2ExceptionRenderer"/>
Hope it helps.