Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds an event listener to the namespace specified by the annotation #932

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

588q9
Copy link

@588q9 588q9 commented Sep 7, 2023

my application requirement need let namespace for more useful,so I add that code for title statement uitlity,if have any problem about destroy hook or more that,I will listen carefully to your advice.

@shutuper
Copy link
Contributor

shutuper commented Sep 14, 2023

You can do it by yourself, in my projects I add:

/**
 * Types that carry this annotation are treated as namespace event listeners.
 * Class should contain methods annotated with:
 * {@link com.corundumstudio.socketio.annotation.OnConnect @OnConnect}
 * {@link com.corundumstudio.socketio.annotation.OnDisconnect @OnDisconnect}
 * {@link com.corundumstudio.socketio.annotation.OnEvent @OnEvent}
 * @see AppServerEventListener
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Namespace {

	/**
	 * The value decides to which namespace current listener should be attached,
	 * the same value can be reused to a few listeners
	 */
	String value() default DEFAULT_NAME; // ""

}

/**
 * A class that listens for application/context events.
 * Registers socket.io namespace listeners and shuts down the server
 * */
@Slf4j
@Component
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true, level = PRIVATE)
public class AppServerEventListener {

	SocketIOServer socketIOServer;

	@EventListener(ApplicationReadyEvent.class)
	public void registerNamespacesEventListeners(ApplicationReadyEvent readyEvent) {
		ConfigurableApplicationContext applicationContext = readyEvent.getApplicationContext();
		Map<String, Object> beansWithNamespace = applicationContext.getBeansWithAnnotation(Namespace.class);

		if (beansWithNamespace.isEmpty()) {
			log.warn("No socket.io namespace listeners found");
		}

		beansWithNamespace.forEach((beanName, bean) -> Optional.ofNullable(
						applicationContext.findAnnotationOnBean(beanName, Namespace.class)
				).ifPresent(namespace -> {
					socketIOServer
							.addNamespace(namespace.value())
							.addListeners(bean, bean.getClass());

					log.info("{} listener added to {} socket.io namespace", beanName, namespace.value());
				})
		);
	}

	@EventListener(ContextClosedEvent.class)
	public void shutDownSocketIOServer() {
		socketIOServer.stop();
	}

}

Then you can create classes annotated with @Namespace & @Component and declare methods annotated with @OnConnect/@OnEvent/@OnDisconnect. With this approach you don't need to create SpringAnnotationScanner bean

@588q9
Copy link
Author

588q9 commented Sep 14, 2023

You can do it by yourself, in my projects I add:

/**
 * Types that carry this annotation are treated as namespace event listeners.
 * Class should contain methods annotated with:
 * {@link com.corundumstudio.socketio.annotation.OnConnect @OnConnect}
 * {@link com.corundumstudio.socketio.annotation.OnDisconnect @OnDisconnect}
 * {@link com.corundumstudio.socketio.annotation.OnEvent @OnEvent}
 * @see AppServerEventListener
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Namespace {

	/**
	 * The value decides to which namespace current listener should be attached,
	 * the same value can be reused to a few listeners
	 */
	String value() default DEFAULT_NAME; // ""

}

/**
 * A class that listens for application/context events.
 * Registers socket.io namespace listeners and shuts down the server
 * */
@Slf4j
@Component
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true, level = PRIVATE)
public class AppServerEventListener {

	SocketIOServer socketIOServer;

	@EventListener(ApplicationReadyEvent.class)
	public void registerNamespacesEventListeners(ApplicationReadyEvent readyEvent) {
		ConfigurableApplicationContext applicationContext = readyEvent.getApplicationContext();
		Map<String, Object> beansWithNamespace = applicationContext.getBeansWithAnnotation(Namespace.class);

		if (beansWithNamespace.isEmpty()) {
			log.warn("No socket.io namespace listeners found");
		}

		beansWithNamespace.forEach((beanName, bean) -> Optional.ofNullable(
						applicationContext.findAnnotationOnBean(beanName, Namespace.class)
				).ifPresent(namespace -> {
					socketIOServer
							.addNamespace(namespace.value())
							.addListeners(bean, bean.getClass());

					log.info("{} listener added to {} socket.io namespace", beanName, namespace.value());
				})
		);
	}

	@EventListener(ContextClosedEvent.class)
	public void shutDownSocketIOServer() {
		socketIOServer.stop();
	}

}

Then you can create classes annotated with @Namespace & @Component and declare methods annotated with @OnConnect/@OnEvent/@OnDisconnect. With this approach you don't need to create SpringAnnotationScanner bean

wow!this look like is a good combine with spring,but what is function of namespace ?I think that can use for distinctive function of socket

@shutuper
Copy link
Contributor

shutuper commented Sep 14, 2023

Namespace just logically groups sockets(each of them can be connected to many namespaces, at least to the default ("/") one, which contains all sockets). In most cases you can just use the default one and group sockets by rooms (also you can add distinctive parametrs to socket)
(more info here: https://socket.io/docs/v4/namespaces/ )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants