My question is : from basic which are the necessary jars that should required in Spring and how could we configure Spring project ?
Go to Spring home page and download Spring (Here, i am using 2.5.x version)
After installing, put the following jar in your classpath
<SPRING_HOME>/dist/spring.jar
Here goes a single bean
package br.com.introducing.Hello;
public class Hello {
private String message;
// getter's and setter's
}
...
Write a single xml to configure your beans as follows
// app.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="hello" class="br.com.introducing.Hello">
<property name="message" value="What do you want ?"/>
</bean>
</beans>
Put your app.xml in root classpath
And your psvm
public static void main(String [] args) {
ApplicationContext appContext = new ClassPathXmlApplicationContext("app.xml");
Hello hello = (Hello) appContext.getBean("hello");
hello.getMessage(); // outputs What do you want ?
}
UPDATE
What is the role of the applicationContext.xml
When using getBean method, it behaves like a Factory pattern. Something like
public class ApplicationContext {
Map wiredBeans = new HashMap();
public static Object getBean(String beanName) {
return wiredBeans.get(beanName);
}
}
As said by Spring in Action book
It is a general-purpose factory, creating and dipensing many types of bean.
But, There is more
Allows you load files
You can publish events
It supports i18n (i18n stands for internationalization)
Suppose here goes messages.properties (root of the classpath)
// messages.properties
messsageCode=What do you want ?
To enable i18n, You must define a bean called messageSource to get advantage of our resource, as follows
<?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-2.5.xsd">
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages"/>
</bean>
</beans>
Now, you can use it
appContext.getMessage("messsageCode", null, null); // outputs What do you want ?
Usually, we do not need to define all of our beans in xml file. You can use annotations (Additional settings needed to enable component scanning) instead of xml, Something like
package br.com.introducing.Hello;
#Component
public class Hello {
private String message;
// getter's and setter's
}
Component annotation says:
Spring, i am a general-purpose bean which can be retrieved through application context
A good resource about Spring is either Spring in Action book or Spring documentation
Advice: read carefully
You can have a look at the article on understanding the webapplicationcontexts and other xml config files in spring
Think this can help you in getting the configurations related to basic spring MVC with ease
You can also use Maven to create and manage projects. You can get an idea about Maven and how to start from here
A directory structure will be created by Maven and there will be a pom.xml inside your project directory. You can mention all dependencies in this file. Eg: for using spring, you can mention the dependency as follows,
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>2.5.3</version>
</dependency>
If you are using Eclipse as IDE, you need to execute the following command,
mvn eclipse:eclipse
This will create a .project file. You can now import the project into Eclipse IDE and start coding your application.
For beginners, Spring reference documentation and books like Spring in Action and Spring Recipes are very useful
Related
My spring java-config application packed as war runs wihout problem on weblogic 12.1.3 so I tried to deploy same war into weblogic 12.2.1 where it causes java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/DispatcherServlet-servlet.xml].
It seems like DispatcherServlet servlet is initialized with XmlWebApplicationContext (default one) instead of AnnotationConfigEmbeddedWebApplicationContext in 12.2.1 even when war is the same.
Has someone any idea what was changed in weblogic implementation since previous version what is causing this problem?
Using same war:
in WLS 12.1.3 it is working without issue, application configures using annotations/java
in WLS 12.2.1 the same application looks for xml configuration at some point instead of configuring it using annotations/java as in 12.1.3.
Had the same problem. I guess there is something wrong with WebLogic 12.2.1.
Try to manually set context class for Spring servlet, like so:
public class ApplicationInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
// <some context configuration>
ServletRegistration.Dynamic spring = container.addServlet("Spring", new DispatcherServlet(context));
// <some servlet configuration>
// Here, set desired context class using 'contextClass' parameter.
spring.setInitParameter("contextClass", context.getClass().getName());
container.addListener(new ContextLoaderListener(context));
}
}
And everything will work fine again :)
Sorry , I can't add a comment on the response of amariq.
Just a comment: if your WebApplicationInitializer extends AbstractDispatcherServletInitializer, you can override the method customizeRegistration like:
#Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
registration.setInitParameter("contextClass", AnnotationConfigWebApplicationContext.class.getName());
}
I managed to get spring-boot 1.3.6.RELEASE working on Weblogic 12.2.1.
I had to create an empty (no declared beans) dispatcherServlet-servlet.xml file on src/main/webapp/WEB-INF directory.
Here is the file content:
<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">
</beans>
In addition, I made my main application class implement WebApplicationInitializer as stated on Spring Boot Ref Guide.
I am not sure if there are now two application contexts, but the one who is answering all my API calls seems to be working fine (dependency injection, aop, jdbc, jpa, logging, session context, actuator, etc).
PS: I have tried #amariq solution but it didn't work on Weblogic 12.2.1, only the one described above.
I had the exact same issue here and tried the solutions suggested above, but they didn't work for me. I finally managed to make it work by doing a few modifications using this GitHub repo as reference.
They main points I could outline are:
pom.xml: add excludes for tomcat-embed-el dependency from spring-boot-starter-web
pom.xml: add dependency for spring-boot-legacy
add web.xml with contextConfigLocation, SpringBootContextLoaderListener and appServlet (in my previous configuration I had no web.xml at all)
Take a look at https://github.com/DISID/disid-proofs/tree/master/spring-boot-weblogic for further details.
I hope it helps.
This is what I've tried so far and my interceptor is not triggered (no "TATATA" in my logs) :
My interceptor AopLoggingInterceptor.java :
package fr.mycompany.bus.flow.reco.ani.custom.interceptor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class AopLoggingInterceptor {
#Around("execution(* org.mule.api.transport.MessageReceiver.routeMessage(org.mule.api.MuleMessage))")
public Object addMonitor(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("TATATA Before");
Object object = pjp.proceed();
System.out.println("TATATA After");
return object;
}
}
META-INF/aop.xml :
<aspectj>
<aspects>
<aspect name="fr.mycompany.bus.flow.reco.ani.custom.interceptor.AopLoggingInterceptor" />
</aspects>
<weaver options="-verbose">
<!-- Weave types that are within the org.mule.* packages. -->
<include within="org.mule.*" />
</weaver>
</aspectj>
My Mule/Spring config file :
<?xml version="1.0" encoding="UTF-8"?>
<mule >
<spring:beans>
<context:component-scan base-package="fr.mycompany.bus" />
<context:annotation-config />
<aop:aspectj-autoproxy />
<!-- Aspect -->
<spring:bean name="aopLoggingInterceptor" class="fr.mycompany.bus.flow.reco.ani.custom.interceptor.AopLoggingInterceptor" />
</spring:beans>
</mule>
My Mule file config consists of one flow with one inbound endpoint, 2 outbound endpoints, loggers and transformers (valid flow widely tested).
VM args :
-XX:PermSize=128M -XX:MaxPermSize=256M -javaagent:D:\path\to\mule\opt\aspectjweaver-1.6.11.jar
Extract from mule file starting in Eclipse which shows weaving is created :
[MuleApplicationClassLoader#2934847] info AspectJ Weaver Version 1.6.11 built on Tuesday Mar 15, 2011 at 15:31:04 GMT
[MuleApplicationClassLoader#2934847] info register classloader org.mule.module.launcher.MuleApplicationClassLoader#2934847
[MuleApplicationClassLoader#2934847] info using configuration /D:/BusToolBox/workspaces/dev/.mule/apps/bus-esb-mrc-reco-ani/classes/META-INF/aop.xml
[MuleApplicationClassLoader#2934847] info register aspect fr.mycompany.bus.flow.reco.ani.custom.interceptor.AopLoggingInterceptor
EDIT
It works nicely with a class included in my project, but not with mule classes :
[MuleApplicationClassLoader#6ad5934d] debug generating class 'fr.mycompany.bus.flow.reco.ani.custom.transformer.CustomerDetailToSiebelRecoAniOutputTransformer$AjcClosure1'
EDIT 2
Here is the best result I can get (by using <context:load-time-weaver />), the loading process tries to look for more classes loaded by difference classloaders is , but it results in :
ERROR 2014-08-08 16:00:46,802 [main] org.mule.module.launcher.application.DefaultMuleApplication: null
java.lang.IllegalStateException: ClassLoader [org.mule.module.launcher.MuleApplicationClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar
If I try to use spring-instrument-3.2.1.RELEASE.jar, I get same result as before (only main classloader is seen). Does it mean there is no hope with Mule ?
Have a look at this example for using Mule and Spring AOP. The example shows how to invoke Around advice for a component, but should be similar for the interceptor.
There is something very important when working with Spring AOP. In spring aop documentation is stated:
Use the simplest thing that can work. Spring AOP is simpler than using
full AspectJ as there is no requirement to introduce the AspectJ
compiler / weaver into your development and build processes. If you
only need to advise the execution of operations on Spring beans, then
Spring AOP is the right choice. If you need to advise objects not
managed by the Spring container (such as domain objects typically),
then you will need to use AspectJ. You will also need to use AspectJ
if you wish to advise join points other than simple method executions
(for example, field get or set join points, and so on).
So if you want that your AopLoggingInterceptor is invoked for MessageReceiver method calls, that is not going to work because the MessageReceiver object is not managed by the Spring container. The Spring container doesn't "see" this objects.
In other words Spring-AOP cannot add an aspect to anything that is not created by the Spring factory. I found that statement here.
I am reading the book 'Camel in Action' and I am unable to work out an example (Section 4.3.4 OsgiServiceRegistry) using OSGi service in the camel route. This is my bean (exposed as OSGi service
public class HelloBean {
public String hello(String name){
System.out.println(" Invoking Hello method ");
return "Hello " + name;
}
}
This is the spring XML file that exposes the above bean as service
<?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:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<bean id="helloBean" class="camelinaction.testbeans.HelloBean" />
<osgi:service id="helloService" interface="camelinaction.testbeans.HelloBean" ref="helloBean" />
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:start" />
<bean ref="helloService" method="hello" />
</route>
</camelContext>
</beans>
When I execute the maven goal 'camel:run', I get the following exception:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloService': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: required property 'bundleContext' has not been set
Please let me know how to set the bundleContext. I am using eclipse equinox as OSGi container.
camel:run just runs a thin non-OSGi runtime using the Spring Camel configs in your project. The message that you are getting is from SpringDM (the thing that instantiates the <osgi:service id="helloService"...>) not being able to locate an OSGi environment. To get this to work you need to install the code inside a supporting container - such as Karaf of Servicemix.
If you'd like to see OSGi working with Camel, check out the Servicemix Bootstraps project at https://github.com/FuseByExample/smx-bootstraps - full documentation is there around installing and tweaking the code. The bundles you'll be interested in there are smx-ponger and smx-ponger-service, which demonstrate the consumption and provision of OSGi services respectively.
I have run into situations like this in the past where I have OSGi dependent components in my camel route and I want to run/debug through an IDE like Eclipse.
If you are looking to debug while you develop, you can deploy to ServiceMix and remotely debug:
http://servicemix.apache.org/developers/remote-debugging-servicemix-in-eclipse.html
Camel 2.10 might support your scenario out of the box with OSGi blueprint:
http://camel.apache.org/camel-run-maven-goal.html
Spring OSGI extensions are fine, but as you can see it is a bit incestuous to test the service interface when you implement and declare the bean from the same spring context. You could of course have bean reference helloBean, but that defeats the purpose.
I am not sure of spring-osgi extension behavior, but at least with the very similar camel-blueprint with pojosr the same test can be with the modified helloService element.
<to uri="bean:camelinaction.testbeans.HelloBean" method="hello" />
Note the unusual fact that where bean id normally references a bean id you are now using the fully qualified interface.
Of course, this has some unfortunate limitations. It works fine if there is only one service instance implementing the desired interface, but there is no obvious way (to me) on how to apply a filter. One alternative in that case is to resort to actually using the bundleContext property of the CamelContext and using the programmatic API. But of course we would like to avoid that in favor of declarative approaches.
I have a Spring XML bean definition that I want to write integration tests for. The XML bean definition is part of a larger application context where several such files are included using <import>. Inside the definition, I reference several beans that are coming from other files.
For my integration test I would like to instantiate the definition standalone and use Mockito mocks for all other beans. Until now, I am using something like this:
FooIntegrationTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class FooIntegrationTest {
#Autowired private ClassUnderTest underTest;
#Autowired private MockedClass mock;
#Test
public void testFoo() {
}
}
FooIntegrationTest-context.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="part-to-test.xml" />
<bean id="mockedClassReferencedByName" class="org.mockito.Mockito" factory-method="mock" c:classToMock="SomeMockedClass" />
<bean class="org.mockito.Mockito" factory-method="mock" c:classToMock="OtherMockedClassReferencedByType" />
<bean class="org.mockito.Mockito" factory-method="mock" c:classToMock="MockedClass" />
...
</beans>
I would like to automate the rather tedious mocking section: Ideally, I would like to have all beans that are not found in the application context to be mocked automatically. The part-to-test.xml uses #Autowired as well as beans that are set by using name references. I only use XML bean definition files, and neither use #Configuration classes nor #Component annotations.
I have looked into how to use a custom context loader in #ContextConfiguration(loader=...), but I have not yet found an appropriate extension point for doing so. Sprinockito does not seem to adress this problem.
Is there some other project out there that already solves this problem? If not, where would I extend Spring to create the mocks automatically?
Here is a short article with a code example. A BeanDefinitionRegistryPostProcessor implementation generates a mock object for each lacking bean definition. The generation part is done with a MocksFactory, here is an example for such a factory.
Just in case anyone is still interested in this question, I have extended the code in the article mentioned by Yves Martin with inheritance, support for #Inject, etc... and created a Github project here: https://github.com/rinoto/spring-auto-mock
I've been working on a project where controllers have been written extending Controller classes. Could I configure and use the POJO based Controllers as well (using #Controller) in the same application?
Many thanks
Thanks jamestastic and skaffman, its working all fine now :)
Below are the lines needed to to be addeded to the web configuration file to have them working together:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" ...line1
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context ...line2
http://www.springframework.org/schema/context/spring-context-2.5.xsd"> ...line3
<context:annotation-config/> ...line4
<context:component-scan base-package="myPackage"/> ...line5
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/> ...line6
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/> ...line7
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> ...line8
</beans>
I was too lazy to not to add line 8 in my main application.
Many thanks
Absolutely. You can mix them together as much as you choose. DispatcherServlet should recognise both old-style and new-style controllers together in the same app.
Yes you can. You'll need to include the Spring JavaConfig project library, as annotation configuration was not part of the 2.5 core.
Here is an example I wrote a while back comparing Google Guice with Spring. Toward the bottom (look for #ImportXml), I show how you can combine Spring XML configuration with annotation configuration. The configuration looks like this:
#Configuration
#ImportXml(locations = "classpath:com/earldouglas/guicespringjc/spring/config.xml")
public class XmlSpringConfiguration {
}
See the Spring Reference regarding combining XML and Annotation configuration. This is from the documentation for Spring 3, but it should still apply (with perhaps minor changes in class names and paths from the old Spring JavaConfig project).
In Spring >= 3.0 use #ImportResource annotation
#Configuration
#ImportResource({ "classpath:/path/to/spring.xml", })
public class AppConfig {
}