Why do I need the #Configuration annotation when using WebSocketMessageBrokerConfigurer? - spring

I'm trying to learn websocket and follow the guide. It advises starting with:
#Configuration
#EnableWebSocketMessageBroker
public class MyConfiguration implements WebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/portfolio").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableStompBrokerRelay("/queue/", "/topic/");
registry.setApplicationDestinationPrefixes("/app/");
}
}
And I don't really understand the meaning of the annotation #Configuration.
As I understand it, the container finds information about the Bean in it, but if only #override is used in this class, then what does it do in this case?

#Configuration
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html
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...
#EnableWebSocketMessageBroker
Add this annotation to an #Configuration class to enable broker-backed messaging over WebSocket using a higher-level messaging sub-protocol...
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/socket/config/annotation/EnableWebSocketMessageBroker.html
That mean without #Configuration, #EnableWebSocketMessageBroker will be ignored by spring container. So WebSocket will not be enabled.

Related

Will declaring #configuration on a class make it a spring bean?

I am having a spring boot project and I have a class declared with #configuration annotation.
will declaring a class with #configuration make it a spring bean ?. so here is my code below
#Configuration
public class DateTimeFormatConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addFormatters(FormatterRegistry registry) {
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
registrar.setUseIsoFormat(true);
registrar.registerFormatters(registry);
}
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new PaginationArgumentResolver());
argumentResolvers.add(new FlightFilterArgumentResolver());
argumentResolvers.add(new CampaignFilterArgumentResolver());
argumentResolvers.add(new ContactListFilterArgumentResolver());
argumentResolvers.add(new UserFilterArgumentResolver());
argumentResolvers.add(new PrimecastAccountFilterArgumentResolver());
argumentResolvers.add(new MessageHistoryFilterArgumentResolver());
}
}
Will the above code results in the creation of a spring bean DateTimeFormatConfiguration in the application context when it is started?
Yes. #Configuration annotated class will register as a spring bean. Check the following snippet from documentation. The primary purpose of #configuration to act as a bean source.
When #Configuration classes are provided as input, the #Configuration
class itself is registered as a bean definition, and all declared
#Bean methods within the class are also registered as bean
definitions.
[1] https://docs.spring.io/spring/docs/4.3.25.RELEASE/spring-framework-reference/htmlsingle/#beans-java-basic-concepts

Spring boot #Inject proxy resolves to null

I'm refactoring an existing application to use Spring Boot. The issues I've faced here are generally of the type "why is this not working anymore".
I have three packages
- nl.myproject.boot
- nl.myproject
- nl.myproject.rest
My current problem is that all #Services that I #Inject in a #RESTController resolve to null when a method is called on them.
The service and dao are part of the nl.myproject package and the reason it's not nl.myproject.core is a legacy issue.
A related issue is that my #Configuration components don't seem to be loaded through #ComponentScan and I have to import them manually. I also had to exclude Test configuration to prevent Test configs from being loaded, which also seemed weird.
Internal calls from the service layer during start up, such as data preparation works normally. Any such manager is also #Injected. This is just to say that any of the typical injection mistakes such as manual instantiation or injecting a class instead of an interface don't apply.
I'd also be grateful for debugging tips. My Java has gotten a little rusty.
#EnableAutoConfiguration
#ComponentScan(basePackages= {
"nl.myproject",
"nl.myproject.boot",
"nl.myproject.dao",
"nl.myproject.service",
"nl.myproject.webapp"},
excludeFilters= {
#ComponentScan.Filter(type=FilterType.REGEX,pattern={".*Test.*"}),
#ComponentScan.Filter(type=FilterType.REGEX,pattern={".*AppConfig"})
}
)
#Configuration
#EnableConfigurationProperties
#Import({
JPAConfig.class,
RestConfig.class,
BootConfig.class
})
public class Startup {
public static void main(String[] args) throws Exception {
SpringApplication.run(Startup.class, args);
}
}
#RestController
#RequestMapping(value="/json/tags")
public class JsonTagController extends JsonBaseController {
#Inject
TagManager tagMgr;
public interface TagManager extends BaseManager<Tag,Long> {
[...]
}
#Service("tagManager")
public class TagManagerImpl extends BaseManagerImpl<Tag, Long> implements
TagManager {
#Inject
TagDao dao;
[...]
#Inject is a annotation specified by JSR-330 (standard) whereas #Autowired is annotation specified by Spring.
They just do the same dependency injection. You can both of them in the same code.
Just the modification (separation of the concerns) you need :
public interface TagManager {
[...]
}
#Service
public class TagManagerImpl implements TagManager {
#Inject
private TagDao dao;
// inject that service rather than extending
#Inject
private BaseManager<Tag,Long> baseManager;
}
public interface BaseManager<Tag,Long> {
[...]
}
#Service
public class BaseManagerImpl<Tag,Long> implements BaseManager<Tag,Long> {
....
}
Just one thing you do for checking, just modify to basePackages= {"nl.myproject"} - just provide only base package, that's enough for spring to scan the components in every package.
Hope this may help :)

How do I Combine REST and Websocket in Spring Boot?

Where to put these blocks of code for websocket configuration in spring boot REST API? In a REST contoller?
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer{
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/socket")
.setAllowedOrigins("*")
.withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app")
.enableSimpleBroker("/chat");
}
}
It should remain in separate class which is under package that spring scanning, its a configuration class
This is not a controller, it is a configuration file, and it has to go with the configuration files. Along with filter configurations, security, servlet configurations...in short, where are the #Configuration, package *.*.configuration

Should I use #Transactional using #EnableTransactionManagement?

I've got a Spring Boot application. Everything works fine. I'm just trying to understand how does transaction manager work, because I have suspicion about my application. In particular, I'm a little confused about annotations.
Here is Application.java (main class):
#SpringBootApplication(exclude = ActiveMQAutoConfiguration.class)
#EnableScheduling
public class Application extends SpringBootServletInitializer
{
#Override
protected SpringApplicationBuilder configure (SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
}
config class DataConfig.java looks like:
#Configuration
#EnableTransactionManagement
#ComponentScan("com.pr.hotel")
#EnableJpaRepositories("com.pr.hotel")
#PropertySource("classpath:application.properties")
public class DataConfig
{
// code
}
I'm worry about #EnableTransactionManagement. What exactly does this annotation mean? Should I use #Transactional in this case (I don't)?
#EnableTransactionManagement does exactly what it says:
Enables Spring's annotation-driven transaction management capability,
similar to the support found in Spring's XML namespace.
Yes, you should still use #Transactional annotation on methods that you want to wrap in a transaction. In the following example the result of saveSomething() wouldn't be applied if maybethrowaneException() threw an exception. Be careful to use org.springframework.transaction.annotation.Transactional and not javax.transaction.Transactional.
The #Transactional annotation tells Spring to control when the data are flushed to the database (typically once the method successfully completes). Without the annotation the data would be flushed immediately.
It's a mechanism to prevent incomplete changes being written to the database when something goes wrong. Further reading: https://dzone.com/articles/how-does-spring-transactional
#Service
public class DataTransformer() {
#Transactional
public void doETL() throws Exception {
loadSomeEntities();
saveSomething();
maybethrowanException();
saveSomethingElse();
}
}

getting #autowired intance null when try trying to do operation on it,throwing null pointer exception

I am trying to save data on gemfire using crud repository. I have created one operation class to call save method of repository but at autowired instance I am getting null pointer exception. Below is my code:
public interface GeodeRepository extends CrudRepository<KeyValueBean, String> {
#Override
public KeyValueBean findOne(String name);
#Override
public <S extends KeyValueBean> Iterable<S> save(Iterable<S> entities);
}
#EnableGemfireRepositories(basePackageClasses = GeodeRepository.class)
#EnableAutoConfiguration
#Configuration
public class Operations {
#Autowired
private GeodeRepository repository;
public void saveKeyValueData(KeyValueBean keyValueBean) {
System.out.println("Repository is : " + repository);
repository.save(Arrays.asList(keyValueBean)); // <--- i am getting
// repository as null so
// getting null pointer
// exception
}
}
When we #Autowired any class make sure, you have declared that class as a #Component.
for example:
#Component
public class Operations {
#Autowired
private GeodeRepository repository;
public void saveKeyValueData(KeyValueBean keyValueBean) {
System.out.println("Repository is : " + repository);
repository.save(Arrays.asList(keyValueBean));
}
}
and try using #Autowired to Operation class to your class
in which class your are calling your saveKeyValueData() method.
So, what is not apparent from your example is how you "bootstrap" your application and it's features (e.g. Repositories) into action.
It is not simply enough to add the Spring #Configuration, Spring Boot's #EnableAutoConfiguration and SD GemFire's #EnableGemfireRepositories annotations and expect everything to be auto-configured and wired up successfully. I.e. you need a bootstrapping mechanism, like Spring Boot, especially if you are using the #EnableAutoConfiguration annotation.
For example...
import org.springframework.boot.SpringApplication;
...
class MyApplication {
public static void main(String[] args) {
SpringApplication.run(Operations.class, args);
}
}
Now, you could remove the #EnableAutoConfiguration from your Operations class and add the #SpringBootApplication to the MyApplication class, like so...
#SpringBootApplication
class MyApplication {
...
}
#SpringBootAppliation combines together Spring's #Configuration with Spring Boot's #EnableAutoConfiguration, along with many other useful meta-annotations, like Spring's #ComponentScan, enabling all sorts of magic to happen.
But, if you are not using Spring Boot, you can always bootstrap you application with the AnnotationConfigApplicationContext, like so..
class MyApplication
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(Operations.class);
applicationContext.registerShutdownHook();
}
}
This is essentially what the Spring Boot, SpringApplication class does for you anyway.
If you are developing a Web application, then of course you can specify the type of ApplicationContext created since you are using Java config, for instance. See here for more details.
Hope this helps!
Cheers,
John

Resources