Spring MVC, Servlet 3.0: how to create resource-ref - spring

I am developing a web application with Spring MVC (4.2.3) and
Servlet 3.0 API, so there is no web.xml.
My WebConfig.java is as follows:
...
import javax.servlet.ServletContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {...})
public class WebConfig extends WebMvcConfigurerAdapter {
#Autowired
ServletContext servletContext;
}
I am creating this spring application by copying from a java application with
Servlet < 3.0, so there is a web.xml which contains this section regarding
the data source:
<resource-ref>
<res-ref-name>jdbc/DefaultDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
</resource-ref>
How do I create such a setting in my Spring MVC application where there is no
web.xml?
In the meantime I have had a look at the "Java Servlet Specification Version 3.0".
It says about #Resource:
The #Resource annotation is used to declare a reference to a resource
such as a data source... This annotation is equivalent to declaring a
resource-ref...
#Resource example:
#Resource private javax.sql.DataSource catalogDS;
public getProductsByCategory() {
// get a connection and execute the query
Connection conn = catalogDS.getConnection();
..
}
In the example code above, a servlet, filter, or listener declares a
field catalogDS of type javax.sql.DataSource for which the reference
to the data source is injected by the container prior to the component
being made available to the application.
The data source JNDI mapping is inferred from the field name
“catalogDS” and type (javax.sql.DataSource). Moreover, the catalogDS
resource no longer needs to be defined in the deployment descriptor.
Unfortunately I don't know how to use it and how to get it connected to Springs JDBCTemplate. Is
public class WebConfig extends WebMvcConfigurerAdapter {
the right location at all?

I implemented a listener by extending
org.springframework.web.context.ContextLoaderListener
and added the annotation
#WebListener.
In that listener the field
#Resource private javax.sql.DataSource catalogDS;
is successfully populated.
http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html
http://docs.oracle.com/javaee/6/api/javax/servlet/annotation/WebListener.html
http://docs.oracle.com/javaee/6/api/javax/annotation/Resource.html

Related

Is ApplicationContext automatically instantiated in Spring?

Is ApplicationContext automatically instantiated in Spring?
If I have my bean defined like this
#Component
public class Car{
...
}
and then I have my config class which tells Spring container where to look for beans through the annotation #ComponentScan
#Configuration
#ComponentScan
public class AppConfig {
...
}
Is Spring automatically creating a context loading all my beans? Or do I have to create it programmatically? If so how do I do it, with something like this?
#Configuration
#ComponentScan
public class AppConfig {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
context.getBean(Car.class);
...
}
Even doing this, there may be a problem, because every time I need the context I have to call new AnnotationConfigApplicationContext...
what is the recommended way to instantiate the context and making him available inside the whole project, maybe as a bean like inside Spring boot app where i can just autowire it.
How Spring Boot can initialize it, load all the beans and let the context available as a bean, ready to be autowired?
No, Application Context isn't automatically instantiated, if you're having a simple and basic Spring Core application. Moreover, your #Configuration class won't scan anything and won't create any beans, if you don't create your Spring Container/Context explicitly with that #Configuration class.
There are several ways of creating Application Context, but the most popular and traditional ones are:
ApplicationContext context = new ClassPathXmlApplicationContext(applicationContext.xml) - implying, that you have your container configuration in the applicationContext.xml file;
ApplicationContext context = new AnnotationConfigApplicationContext(ConfigClass.class); - implying, that your ConfigClass is the #Configuration class.
However, if you have the Spring Boot application annotated with #SpringBootApplication, then the Application Context will be automatically instantiated for you, because:
#SpringBootApplication annotation consists of:
#EnableAutoConfiguration - which enables Spring Boot’s auto-configuration mechanism;
#ComponentScan - which enable #Component scan on the package where the application is located;
#Configuration - allows to register extra beans in the context or import additional configuration classes.
and this will spin up the context for you.
You can obtain the reference to the Spring Context created by Spring Boot, by the factory method you have in your main method: SpringApplication.run(MainClass.class, args);
This returns the reference to the Application Context and you can assign it to variable like this:
ApplicationContext context = SpringApplication.run(MainClass.class, args)

Using #PropertySouce in #Component

I tried to use #PropertySource in a #Component like:
#Component
#PropertySource("somepropertiesfile.properties")
public class Student {
...
}
It worked fine.
I want to understand, what is the different between using #PropertySource with #Component and #PropertySource with #Configuration.
Is there any difference or impact of using #PropertySource with #Component.
Configuration is itself a Component type, look into the #Configuration annotation implementation below.
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Component
public #interface Configuration {
}
From API
Component: Indicates that an annotated class is a "component". Such classes are considered as candidates for auto-detection when using annotation-based configuration and classpath scanning.
Configuration: Indicates that a class declares one or more #Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.
The #Bean annotation is used to indicate that a method instantiates, configures and initializes a new object to be managed by the Spring IoC container. These are same as Spring’s XML configuration. You can use #Bean annotated methods with any Spring #Component, however, they are most often used with #Configuration beans.
Here also you can use #PropertySource in #Component class but these are most suitable for #Configuration classes as it is a configuration related task.
You can refer Doc for detailed information.

Spring #configure annotation usage without bean definitions

I have some experience with spring dependency injection and transaction management but I am new to spring security. When i was reading an article related to spring security, I found that #Configuration annotation is used in an example but there were no bean definitions to be found.
According to my understanding, #Configuration annotation is used in classes which contain bean definitions. I need to know that what does the #Configuration annotation do in this example.
#Configuration
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {
#Autowired
DataSource dataSource;
... // web stuff here
#Override
public configure(AuthenticationManagerBuilder builder) {
builder.jdbcAuthentication().dataSource(dataSource).withUser("dave")
.password("secret").roles("USER");
}
}
Thank you
It's not mandatory to have Bean definitions in Spring managed classes.
In this case #Configuration (which wraps #Component) is used to indicate to Spring that this class should be instantiated and all it's dependencies should be injected - in this case that's DataSource and AuthenticationManagerBuilder. This is an example of Inversion of Control principle.
Spring also provides these ConfigurerAdapter hook points, where you can tweak the default configuration of an already instantiated component.
This is exactly what is happening in your Configuration class.

#Provider AND Registration in Application(ResourceConfig) requirement for custom MessageBodyWriter/Reader?

Is there a requirement that a custom MessageBodyWriter and MessageBodyReader must not only be annotated by #Provider annotation AND also be included in the Application configuration through Application or ResourceConfig. If yes, why?
My train of thought was that, if classes are annotated with #Provider then the JAX-RS runtime by default loads such classes as it's runtime component. Declaring the same class inside the Application makes is a redundant exercise. It appears my train of thought is wrong, but I am looking for some kind of explanation on how and why this has been designed this way(ie both annotation and Application configuration).
I can understand that some form of Application configuration would be required on the Jersey Client side, but am not very confident about that either.
For instance, the JavaMarshaller class below has been annotated with #Provider
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.Provider;
#Provider
#Produces("application/example-java")
#Consumes("application/example-java")
public class JavaMarshaller implements MessageBodyReader, MessageBodyWriter {
.......
Now in the Application class is it required to do as below?
#ApplicationPath("services")
public class ShoppingApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> classes = new HashSet<Class<?>>();
public ShoppingApplication() {
classes.add(JavaMarshaller.class);
}
.........
Typically, the registration of classes dynamically is a feature of application servers. Since your'e deploying to tomcat, Jersey will likely expect that you're listing your providers and resources in your Application class.
If you were deploying to a full app server, like WildFly or GlassFish, you wouldn't need to do this.

Data from #RequestScoped bean is shared in different browsers

I have a #RequestScoped bean with a List property.
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import org.springframework.stereotype.Controller;
#Controller
#ManagedBean
#RequestScoped
public class MyBean implements Serializable {
private List list;
// getters and setters
}
This property is linked to a datatable:
<ice:dataTable value="#{myBean.list}" ..other stuff.. />
The List is dynamically filled with no problem, and the datatable is displayed with no problems. But if, I navigate to another page, and then go back to the initial page the datatable is still with the data of the initial request. It shouldn't be empty again? If the bean is request scoped it should be destroyed after the request, and I should get and empty datatable as the beginning.
Even more strange is that if I open the page in one browser (like Firefox), fill the datatable with a request, then I open another browser (like Chrome) and go to the datatable page, it is filled with the data from previous request from another browser! I think the bean is behaving like an application one.
Any ideas?
Update 1: The class is not static neither its variables. Also, I disable tomcat cache, but still not working.
Update 2: I think probably found the problem. My backing beans are annotated with #Controller from Spring. I use this annotation because then use #Autowired to bind services. Could be this is creating a singleton and that why is not being created and destroyed with every request? I think pretty sure the problem is in the mix of Spring and JSF2 annotations.
You shouldn't manage a single bean by multiple different bean management frameworks like JSF, CDI and Spring. Choose the one or the other. When managing the bean by for example Spring's #Controller, all bean management related annotations of other frameworks like JSF's #ManagedBean and CDI's #Named are ignored.
I don't do Spring and I have no idea why you're using it instead of the standard Java EE 6 API, but the symptoms and documentation indicates that the scope of such a Spring bean indeed defaults to the application scope. You need to specify the bean scope by Spring #Scope annotation. You would also like to remove the JSF bean management annotations since they have no value anymore anyway and would only confuse the developer/maintainer.
#Controller
#Scope("request")
public class MyBean implements Serializable {
// ...
}
Alternatively, you can also get rid of Spring #Controller annotation and stick to JSF #ManagedBean. You can use #ManagedProperty instead of #Autowired to inject another #ManagedBean instance or even a Spring managed bean (if you have Spring Faces EL resolver configured), or the Java EE standard #EJB to inject an #Stateless or #Stateful instance.
E.g.
#ManagedBean
#RequestScoped
public class MyBean implements Serializable {
#EJB
private SomeService service;
// ...
}
See also:
Spring JSF integration: how to inject a Spring component/service in JSF managed bean?

Resources