230 likes | 368 Views
Intermediate Spring. Matt Wheeler. Notes. This is a training NOT a presentation Please ask questions Prerequisites Introduction to Java Stack Basic Java and XML skills Installed LdsTech IDE (or other equivalent – good luck there ;). Review. Bean lifecycle
E N D
Intermediate Spring Matt Wheeler
Notes • This is a training NOT a presentation • Please ask questions • Prerequisites • Introduction to Java Stack • Basic Java and XML skills • Installed LdsTech IDE (or other equivalent – good luck there ;)
Review • Bean lifecycle • XML Schema-based Configuration (namespace handlers) • Lifecycle hooks • Bean Initialization (JSR 250, @PostConstruct, …) • Bean post processors • Component scanning • Spring Component Annotations • DI Annotations (JSR 330, @Inject, @Named)
Overview • Advanced Injection • Spring EL • Additional Injection Annotations • Providers • Application Context web integration • Testing framework
Spring EL (SpEL) • Allows access to Spring beans and properties • Supports querying and manipulating object graph at runtime • Similar syntax to Unified EL (but more extensive) • Method invocation, string templating • Namespace handlers use it to inject references into attributes • For more specifics, please see the Spring docs: • http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html
Spring EL Examples • We recommend only using this when necessary • For example • When extracting a property from a map • Or injecting a reference into a namespace handler <property name="someProperty" value="#{systemProperties['someValue']}" /> <jee:jndi-lookup id="databasePassword" jndi-name="dbPassword" /> <jee:jndi-lookup id="databaseUsername" jndi-name="dbUsername"/> <data-source driver-class="org.h2.Driver" url="jdbc:h2:mem:stack-starter;MODE=Oracle" user="#{databaseUsername}" password="#{databasePassword}" override="true" db-env="EMBEDDED"/>
Additional Injection Annotations • Many additional injection annotations • Please refer to the Spring documentation here: • http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-annotation-config
Providers • Providers allow us to defer instantiation or accessing a resource until it is accessed • Providers facilitate (from the JavaDoc): • Retrieving multiple instances • Lazy or optimal retrieval of an instance • Breaking circular dependencies • Abstracting scope so you can look up an instance in a smaller scope from an instance in a containing scope
Previous Training Lab • We used the Named annotation to select the prototypeRabbit to inject into the farm as the prize rabbit • The result was something like the following • Does anyone see any problem with this? @Component public class Farm { @Inject @Named("prototypeRabbit") private Provider<Rabbit> prizeRabbit; … }
Provider Demo DEMO
Lab 1: Providers https://tech.lds.org/wiki/Intermediate_Spring#Lab_1_Advanced_Injection
Web Context Listener • Loading application context in a web environment
Traditionally • Previously we have loaded application contexts with something like: • In a web environment however • You will want the context to automatically be loaded on startup • And be shared across the entire application ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); SomeBeansomeBean = context.getBean(SomeBean.class);
Servlet Listeners • The Java Servlet spec provides a listener (startup hook) • Triggers these listeners to run on startup • Spring utilized this functionality and created a listener • Will load the application context on start up
Context Loader Listener • Specifically the following configures this listener in web.xml: • And utilizes the following context parameter <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:META-INF/spring/applicationContext.xml,classpath:*beans.xml</param-value> <param-value>classpath:anotherContext.xml</param-value> </context-param>
Application Contexts and Servlets • Servlets not instantiated by Spring • Instantiated by the servlet container • Spring unable to inject dependencies • However Spring provides a way to access the application context
Application Context and Servlet • For the given servlet configuration (web.xml) • Application Context accessed as follows: <servlet> <servlet-name>servlet</servlet-name> <servlet-class>org.lds.training.TrainingServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>servlet</servlet-name> <url-pattern>/servlet</url-pattern> </servlet-mapping> public class TrainingServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Context loader listener stores context in the servlet context - which is why it is required ApplicationContextapplicationContext= WebApplicationContextUtils.getWebApplicationContext(getServletContext()); SomeBeansomeBean = (SomeBean) applicationContext.getBean(SomeBean.class); someBean.printSomething(); } }
A Better Way • Spring provides a servlet that delegates to a bean that is Spring managed • Allowing annotations and injection • Called an HttpRequestHandler • Create a Spring bean that matches the name of the servlet name • This provides the mapping between the two
Utilizing a Spring Request Handler • The configuration: <!– web.xml --> <servlet> <servlet-name>trainingHandler</servlet-name> <servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>trainingHandler</servlet-name> <url-pattern>/trainingHandler</url-pattern> </servlet-mapping> <!– applicationContext.xml --> <bean id="trainingHandler" class="org.lds.training.TrainingRequestHandler" /> //Java Implementations public class TrainingRequestHandler implements HttpRequestHandler { @Inject private SomeBeansomeBean; public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ someBean.printSomething(); } }
Spring MVC and Application Contexts • Spring MVC provides and even better way to integrate with the web container • Look forward to further discussion of this in a future training
Lab 2: Web Context Listener https://tech.lds.org/wiki/Intermediate_Spring#Lab_2_Web_Context_Listener
Credit where credit is due • http://springsource.org • Spring Recipies 2nd Edition (Gary Mak, Josh Long and Daniel Rubio)