I am trying to wire beans using Annotations.. When a beans is not present in the beans.xml config file, i am getting a null pointer exception.. i expect the required=false attribute to fix this.. is that a fair expectation? If so, why is it still throwing exception even if i set required as false for that missing bean...
package com.rajkumar.spring;
import org.springframework.beans.factory.annotation.Autowired;
public class Log {
private ConsoleWriter consoleWriter;
private FileWriter fileWriter;
#Autowired
public void setConsoleWriter(ConsoleWriter consoleWriter) {
this.consoleWriter = consoleWriter;
}
#Autowired(required=false)
public void setFileWriter(FileWriter fileWriter) {
this.fileWriter = fileWriter;
}
public void writeToFile(String message) {
fileWriter.write(message); // this is throwing the error as the bean is comments in the XML file..
}
public void writeToConsole(String message) {
consoleWriter.write(message);
}
}
My Beans.xml is below..
<?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-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<bean id="log" class="com.rajkumar.spring.Log"></bean>
<bean id="consoleWriter"
class="com.rajkumar.spring.ConsoleWriter">
</bean>
<!-- <bean id="fileWriter" class="com.rajkumar.spring.FileWriter"></bean> -->
<context:annotation-config></context:annotation-config>
</beans>
required=false is to only make spring container dependency checking optional and it avoids correpsonding bean not found exception like.. required a bean of type 'com.rajkumar.spring.FileWriter' that could not be found.
Please note that injected object is still null here, hence you are seeing NullPointerException.
Hope this helps you.
Try to add the #Component Annotation above your class definition.
#Component
public class Log {
...
Without Spring won't recognize your class to inject something somewhere and your fields will remain null. You might also want to add ComponentScan to your configuration.
public void writeToFile(String message) {
fileWriter.write(message); // this is throwing the error as the bean is comments in the XML file..
}
The error is throwing because there is no bean injected to fileWriter if the bean will not be injected then try to validate if the object is not null before use it.
public void writeToFile(String message) {
if (fileWriter!=null)
fileWriter.write(message); // this is throwing the error as the bean is comments in the XML file..
}
Another approach is to use a #PostConstruct, for example:
#PostConstruct
public void initBean(){
if (fileWriter ==null) fileWriter = new SomeFileWriter();
}
In that case there is no need to evaluate fileWriter on writeToFile method
Also you can use a init method instead of #PostConstruct
Like this:
<bean id="log" class="com.rajkumar.spring.Log" init-method="myInit"></bean>
then on myInit() method try to initialize your null object.
Related
I started to work in a simple Spring web-service and getting the following errors provided below,
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'blogEntryController':
Injection of autowired dependencies failed; nested exception
is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private core.services.BlogEntryService
rest.mvc.BlogEntryController.service; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [core.services.BlogEntryService] found for
dependency: expected at least 1 bean which
qualifies as autowire candidate for this dependency. Dependency
annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
The project structure is as following,
Spring MVC project structure
I have the following service code,
package core.services;
import core.entities.BlogEntry;
public interface BlogEntryService {
public BlogEntry find(Long id); // Returns the BlogEntry or null if it can't be found
public BlogEntry delete(Long id); // Deletes the found BlogEntry or returns null if it can't be found
public BlogEntry update(Long id, BlogEntry data);
}
and, the following Controller code,
#Controller
#RequestMapping("/rest/blog-entries")
public class BlogEntryController {
#RequestMapping("/")
public String test(){
return "view";
}
public BlogEntryController() {
}
#Autowired
private BlogEntryService service;
public BlogEntryController(BlogEntryService service)
{
this.service = service;
}
#RequestMapping(value="/{blogEntryId}",
method = RequestMethod.GET)
public ResponseEntity<BlogEntryResource> getBlogEntry(
#PathVariable Long blogEntryId) {
BlogEntry entry = service.find(blogEntryId);
if(entry != null)
{
BlogEntryResource res = new BlogEntryResourceAsm().toResource(entry);
return new ResponseEntity<BlogEntryResource>(res, HttpStatus.OK);
} else {
return new ResponseEntity<BlogEntryResource>(HttpStatus.NOT_FOUND);
}
}
}
Update: Dispatcher Servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="rest.mvc"/>
<mvc:annotation-driven/>
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
I created the empty constructure as it was asked by the debugger earlier. I cant even see the view.jsp file returned from the test method. What should I do now ?
As I stated in my first comment beneath your question, you are missing the implementation class of the interface. An implementation class could be the one below, however you have to provide the functionality of the methods:
#Service
public class BlogEntryServiceImpl implements BlogEntryService {
public BlogEntry find(Long id) {
//Do your stuff here
}
public BlogEntry delete(Long id) {
//Do your stuff here
}
public BlogEntry update(Long id, BlogEntry data) {
//Do your stuff here
}
}
#Autowired
private BlogEntryService service;
Above lines says you are having class BlogEntryService annotated
with #Service or mentioned in bean tag or as component scan(package) in dispatcher-servlet xml.
If you are missing mentioning in any of one place you will get the exception No qualifying bean of type [core.services.BlogEntryService] found for dependency:
So your BlogEntryService interface should be
#Service
public interface BlogEntryService {
Update : In dispathcer-servlet.xml you have to mention the packages to scan for beans.In your case it is rest.mvc.Since it's an Interface you should have the implemented class(annotated with #Service),which will have definition of interface methods.
<context:component-scan base-package="Your Service layer Package" />
It looks that BlogEntryService bean class is not provided. Do you have some implementation class annotated wit #Service?
Either you provide an implementation class for your interface and annotate it with #service, OR make the BlogEntryService interface extend CrudRepository and Spring will provide you with the proper implementation for your cruds :save, getAll, find...
It looks like an implementation of your service is missing.
Just annotating an interface with #Service is not enough for Spring to generate a bean unless you are extending your interface with some of the specific Spring Data interface (CrudRepository, Repository ...). In that specific case and if you respect sone convention Spring will be able to automatically generate the implementation for you.
Please have a look to the documentation: http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories
I am learning Spring framework (more generally Java EE).
I like the feature of passing the configuration using xml files. I started by the this example and it worked fine.
The only problem is that once I add my custom xml configuration with beans to set the attribute value inside the controller it doesn't work anymore, in the server log file it says Caused by: java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'com.example.controller.FirstController#0' bean method (...) then it lists all the methods in the controller exactly like if I defined multiple methods with identical RequestMapping (which is not the case).
I wanted to set a single attribute, but it seems that because of that the entire autoconfiguration doesn't work anymore.
Before
Main class
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
Controller class
#RestController
#RequestMapping("first")
public class FirstController {
protected final Logger log = LoggerFactory.getLogger(getClass());
#RequestMapping("test")
public String test() {
log.info("Test");
return "OK";
}
}
After
Main class
#Configuration
#ComponentScan
#EnableAutoConfiguration
#ImportResource("classpath:config.xml")
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
Controller class
#RestController
#RequestMapping("first")
public class FirstController {
protected final Logger log = LoggerFactory.getLogger(getClass());
private String testingbean;
public void setTestingbean(String testingbean) {
this.testingbean = testingbean;
}
#RequestMapping("test")
public String test() {
log.info("Test");
return "OK";
}
#RequestMapping("beantest")
public String testBeans() {
return testingbean;
}
}
Config.xml 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- test bean -->
<bean class="com.example.controller.FirstController">
<property name="testingbean" value="works"/>
</bean>
</beans>
In the Before version after accessing /first/test it returned OK, now I get blank page and Ambiguous mapping found error in the log file.
Could someone explain to me how to mix Spring Boot autoconfiguration with custom defined beans?
I would also recommend to use property files to externalize configuration if possible.
EDIT: Spring boot provides fine documentation on that topic.
The problem can be the combination of XML configuration and default component scan - the same bean can be defined twice. If this is the case consider "manual" exclude via http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScan.html#excludeFilters--
My Aspect class will be ,
#Configuration
#EnableAspectJAutoProxy
#Component
#Aspect
public class AspectClass {
#Before("execution(* com.pointel.aop.test1.AopTest.beforeAspect())")
public void logBefore(JoinPoint joinPoint) {
System.out.println("Before running the beforeAspect() in the AopTest.java class!");
System.out.println("Hijacked Method name : " + joinPoint.getSignature().getName());
System.out.println("************************");
}
}
My other java Class
public class AopTest {
public void beforeAspect() {
System.out.println("This is beforeAspect() !");
}
}
My Main Class is
public class MainMethod {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext("ApplicationContext/applicationContext.xml");
AopTest test = (AopTest)context.getBean("bean1");
test.beforeAspect();
}
}
My applicationContext.xml is ,
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<bean id="bean1" class="com.pointel.aop.test1.AopTest" />
</beans>
In this the #Before("execution(* com.pointel.aop.test1.AopTest.beforeAspect())") in the AspectClass will not be executed before the beforeAspect() in the AopTest , when running Main method.
Good answers are definitely appreciated.
First of all if you're going to use an annotation based configuration, use AnnotationConfigApplicationContext instead of FileSystemXmlApplicationContext. And get rid of the applicationContext.xml file and simply add a #Bean method in your configuration class. Something like this:
#Configuration
#EnableAspectJAutoProxy
#ComponentScan(basePackages = "your.aspect.package")
public class AspectConfig {
#Bean
public AopTest aopTest() {
return new AopTest();
}
}
In your main
public class MainMethod {
public static void main(String[] args) {
AnnotationConfigApplicationContextcontext = new AnnotationConfigApplicationContext(AspectConfig.class);
// don't forget to refresh
context.refresh();
AopTest test = (AopTest)context.getBean("aopTest");
test.beforeAspect();
}
}
In AspectClass you should have #Component, #Aspect, and your method should have the advice or pointcut annotation like #Before. It needs to be a #Component, so that Spring knows to scan it.
Here some code need to add in xml to use annotations-
1.for #component annotation.
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
2.after that use component scan to get all annotated bean class which use #component annotation,and use aop autoproxy-
<context:annotation-config/>
<context:component-scan base-package="mypackage"></context:component-scan>
<aop:aspectj-autoproxy>
</aop:aspectj-autoproxy>
for examples visit-www.technicaltoday.com/p/spring.html
You are missing the point cut definition in your aspect class.
For example;
#Pointcut("execution(* *.advice(..))")
public void logBefore(){}
#Before("logBefore()")
public void beforeAdvicing(){
System.out.println("Listen Up!!!!");
}
You first have to defin the point to weave your aspect to. You do this by using Point cuts.It is the point cut name you give within your #Before annotation. Have a look at my blog post for more information # http://dinukaroshan.blogspot.com/2010/06/aop-with-spring.html
I don't see your AspectClass in the beans configuration. You should also declare it as a Bean.
I'm writing my own scope (i.e. a class which implements org.springframework.beans.factory.config.Scope) and I need some beans injected. How do I do that?
Background: Spring must create all scope beans first so that I can define which beans go into the scope. But what about beans that I need to build the scope in the first place?
I came up with this workaround which seems to be pretty safe but I'd like to hear comments (or maybe my answer gives you some better ideas):
Define the scope and give it setters (instead of using #Autowired)
Create a "scope configurer" bean:
public CustomScopeConfigurer {
#Autowired private Foo foo;
private CustomScope scope;
public CustomScopeConfigurer( CustomScope scope ) {
this.scope = scope;
}
#PostConstruct
public void initScope() {
scope.setFoo( foo );
}
}
This configurer bean must not be lazy.
Reasoning:
The scope itself can't use autowiring because it is created before the first bean. While it might be created later, you can be sure that it will be created before every other bean. So autowiring can't work reliably.
The configurer bean will be created alongside all the other beans but after the scope. So autowiring will work for it.
Since the configurer bean isn't initialized lazy, it will be created before the rest of the application can see the application context. This means that no beans for the scope (i.e. beans with #Scope("custom")) can have been created at this time - the scope can't be "active", yet -> Spring won't have tried to put any beans into it, yet.
The scope itself is usually created as a static constant somewhere. That's why we have to pass it as an argument to the constructor.
You can do that very simply.
Consider the below Custom scope class:
package com.way2learn;
import java.util.Map;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
public class MyCustomScope implements Scope{
private Map<String, Object> scope;
public void setScope(Map<String, Object> scope) {
this.scope = scope;
}
#Override
public Object get(String name, ObjectFactory<?> objectFactory) {
checkAndClear();
Object bean=scope.get(name);
if(bean==null){
bean=objectFactory.getObject();
scope.put(name,bean);
}
return bean;
}
private void checkAndClear() {
//Some logic to check condition and clear the scope
}
//optional methods
#Override
public Object remove(String name) {
// TODO Auto-generated method stub
return null;
}
#Override
public void registerDestructionCallback(String name, Runnable callback) {
}
#Override
public Object resolveContextualObject(String key) {
// TODO Auto-generated method stub
return null;
}
#Override
public String getConversationId() {
// TODO Auto-generated method stub
return null;
}
}
It has dependency on java.util.Map.
You can not autowire using #Autowired it as #Autowired annotation works after AutoWiredAnnotationBeanPostProcessor only.
But Custom scopes will be registered before AutoWiredAnnotationBeanPostProcessor.
So you can manually inject Map into MyCustomScope class as below:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
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-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
<util:map key-type="java.lang.String" value-type="java.lang.Object" id="custScopeMap"/>
<bean id="myCustomScope" class="com.way2learn.MyCustomScope">
<property name="scope" ref="custScopeMap"/>
</bean>
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="myScope" value-ref="myCustomScope"/>
</map>
</property>
</bean>
</beans>
I tried it. It works fine. And I found a bug in Aaron Digulla's answer i.e.
Consider the below scenario: First Spring's CustomScopeConfigurer bean will be created, immediately CustomScope bean will be created and now our custom scope is ready to use. After some time Aaron Digulla's CustomScopeConfigurer will be created which initializes foo into CustomScope. But what happenes if some custom scoped beans are created after CustomScope registration and before Aaron Digulla's CustomScopeConfigurer bean creation? For those beans there will be not foo in the CustomScope bean.
I am trying to get Aspect working with Spring 3 and annotations.
#Aspect
public class AttributeAspect {
#Pointcut("#annotation(com.mak.selective.annotation.Attribute)")
public void process(){
System.out.println("Inside Process ....");
}
#Around("process()")
public void processAttribute(){
System.out.println("Inside Actual Aspect ..");
}
}
XML:
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
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/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<aop:aspectj-autoproxy proxy-target-class="false" />
<context:component-scan base-package="com.mak.selective.annotation.*" />
<bean name="attribute" class="com.mak.selective.annotation.AttributeAspect"/>
</beans>
MY Test to test the Aspect:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("/springcontext/*.xml")
public class AttributeTest {
#Attribute(tableName = "firstTable", columnName = "New Column")
private void getAttribute() {
System.out.println("Inside Attribute call...");
}
#Test
public void testAttributeAspect() {
getAttribute();
}
}
With this code i can only see "Inside Attribute call..." but nothing from Aspect.
Please guide.
Got this working by making a new Object (Component) and injected to the Junit test class.
Good to see that you got it working from XML, but you could have also done it from annotations.
The issue is that the #Aspect annotation is not a Spring stereotype, so the scanner is not registering the aspect as a Spring Bean. Just add either #Service or #Component above or below #Aspect and it will be registered.
Also, either directly name the bean (e.g., #Service("myNamedService")) or have it implement an interface (e.g., public class AttributeAspect implements IAspect {), as per standard Spring design.
You need to use real AspectJ if you want to intercept invocations of methods within the same bean form where it is invoked. (What you have done, should work if the method testAttributeAspect() is located in an other bean.)
How to do real AspectJ?
Using the AspectJ compiler and weaver enables use of the full AspectJ language, and is discussed in Section 7.8, “Using AspectJ with Spring applications”.
#See Spring Reference
A few things:
Firstly, when you do around advice you need to write the advice method like this:
#Around(...)
public void aroundAdviceMethod(ProceedingJoinPoint pjp) throws Throwable {
try {
System.out.println("before...");
pjp.proceed();
}
finally {
System.out.println("After...");
}
}
But also (and this at least applies when you're using proxies, not entirely sure in your case), the method you're putting advice on needs to be public (yours isn't), spring managed (via #Component or otherwise) and called external from the class so the proxy can take effect (also not the case in your example). So you need something like this:
#Component
public class SomeClass {
#Attribute
public void someMethodCall() {
System.out.println("In method call");
}
}
public class SomeUnitTest {
#Autowired SomeClass someClass;
#Test
public void testAspect() {
someClass.someMethodCall();
}
}