├── .gitignore
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── zbum
│ │ └── example
│ │ └── socket
│ │ └── server
│ │ ├── Application.java
│ │ ├── netty
│ │ ├── ChannelRepository.java
│ │ ├── TCPServer.java
│ │ └── handler
│ │ │ ├── SomethingChannelInitializer.java
│ │ │ └── SomethingServerHandler.java
│ │ └── repository
│ │ ├── RepositoryConfiguration.java
│ │ ├── User.java
│ │ └── UserRepository.java
└── resources
│ ├── logback.xml
│ ├── properties.production
│ ├── nettyserver.properties
│ └── springjpa.properties
│ └── properties
│ └── local
│ ├── nettyserver.properties
│ └── springjpa.properties
└── test
└── java
└── com
└── zbum
└── example
└── socket
└── server
├── netty
└── handler
│ └── SomethingServerHandlerTest.java
└── repository
└── UserRepositoryTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | target/
3 | netty-spring-with-jpa.iml
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Netty-spring-example with JPA
2 | TCP communication server with Netty, spring-boot, spring-data-jpa
3 |
4 | This TCP Communication Service is a simple example for developer who want to make tcp service with Spring-Boot, Spring-Data-JPA and Netty.
5 |
6 | ## Feature
7 | * Telnet Client can send message to other telnet client.
8 | * Telnet Client can retrieve User Information from RDBMS(H2 DB).
9 |
10 | ## Install
11 | This example uses embedded DBMS(h2 db). So, you don't need to install any DBMS.
12 | But you have to use below DDL and DML.
13 |
14 | ```sql
15 | CREATE TABLE USER
16 | (
17 | ID BIGINT AUTO_INCREMENT PRIMARY KEY NOT NULL,
18 | PHONE_NUMBER VARCHAR(255),
19 | USERNAME VARCHAR(255),
20 | USE_YN BOOLEAN DEFAULT TRUE
21 | );
22 | CREATE UNIQUE INDEX UK_SB8BBOUER5WAK8VYIIY4PF2BX_INDEX_2 ON USER (USERNAME);
23 | ```
24 |
25 | ```sql
26 | INSERT INTO PUBLIC.USER (ID, PHONE_NUMBER, USERNAME, USE_YN) VALUES (1, '010-1111-2222', 'zbum', true);
27 | INSERT INTO PUBLIC.USER (ID, PHONE_NUMBER, USERNAME, USE_YN) VALUES (2, '010-1111-3333', 'manty', true);
28 | INSERT INTO PUBLIC.USER (ID, PHONE_NUMBER, USERNAME, USE_YN) VALUES (3, '010-1111-4444', 'jibumjung', true);
29 | ```
30 |
31 | ## How to use
32 | * Run com.zbum.example.socket.server.netty.Application with IDE or Maven
33 | ```
34 | $ mvn spring-boot:run
35 | ```
36 | * Connect to this server by telnet command.
37 | ```
38 | $ telnet localhost 8090
39 | Trying ::1...
40 | Connected to localhost.
41 | Escape character is '^]'.
42 | Your channel key is /0:0:0:0:0:0:0:1:57220
43 | ```
44 | * Your channel key (ID) is /0:0:0:0:0:0:0:1:57220
45 | * Connect to this server by telnet command on annother terminal.
46 | ```
47 | $ telnet localhost 8090
48 | Trying ::1...
49 | Connected to localhost.
50 | Escape character is '^]'.
51 | Your channel key is /0:0:0:0:0:0:0:1:57221
52 | ```
53 | * From now, you can send message to /0:0:0:0:0:0:0:1:57220 channel by below
54 | ```
55 | /0:0:0:0:0:0:0:1:57220::I Love You!!!
56 | ```
57 | * Then, you can receive Message like below
58 | ```bash
59 | $ telnet localhost 8090
60 | Trying ::1...
61 | Connected to localhost.
62 | Escape character is '^]'.
63 | Your channel key is /0:0:0:0:0:0:0:1:57220
64 | I Love You!!!
65 | ```
66 |
67 | * Then, you can retrieve user data by command below.
68 | ```bash
69 | $ telnet localhost 8090
70 | Trying ::1...
71 | Connected to localhost.
72 | Escape character is '^]'.
73 | Your channel key is /0:0:0:0:0:0:0:1:63390
74 | name?zbum
75 | 010-1111-2222
76 | name?manty
77 | 010-1111-3333
78 | name?all
79 | zbum:010-1111-2222
80 | manty:010-1111-3333
81 | ```
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.zbum.example.socket.server
8 | netty-spring-example-with-jpa
9 | 1.0-SNAPSHOT
10 |
11 |
12 | org.springframework.boot
13 | spring-boot-starter-parent
14 | 1.2.5.RELEASE
15 |
16 |
17 |
18 | org.springframework.boot
19 | spring-boot-starter-data-jpa
20 |
21 |
22 | io.netty
23 | netty-all
24 | 4.0.28.Final
25 | compile
26 |
27 |
28 |
29 | com.h2database
30 | h2
31 | 1.3.176
32 |
33 |
34 |
35 | junit
36 | junit
37 | 4.8.1
38 | test
39 |
40 |
41 | org.mockito
42 | mockito-core
43 | 2.0.31-beta
44 | test
45 |
46 |
47 | org.springframework
48 | spring-test
49 | 4.0.4.RELEASE
50 | test
51 |
52 |
53 |
54 |
55 |
56 |
57 | org.springframework.boot
58 | spring-boot-maven-plugin
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/main/java/com/zbum/example/socket/server/Application.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.zbum.example.socket.server;
17 |
18 | import com.zbum.example.socket.server.netty.ChannelRepository;
19 | import com.zbum.example.socket.server.netty.TCPServer;
20 | import com.zbum.example.socket.server.netty.handler.SomethingChannelInitializer;
21 | import io.netty.bootstrap.ServerBootstrap;
22 | import io.netty.channel.ChannelOption;
23 | import io.netty.channel.nio.NioEventLoopGroup;
24 | import io.netty.channel.socket.nio.NioServerSocketChannel;
25 | import io.netty.handler.logging.LogLevel;
26 | import io.netty.handler.logging.LoggingHandler;
27 | import org.springframework.beans.factory.annotation.Autowired;
28 | import org.springframework.beans.factory.annotation.Qualifier;
29 | import org.springframework.beans.factory.annotation.Value;
30 | import org.springframework.boot.SpringApplication;
31 | import org.springframework.boot.autoconfigure.SpringBootApplication;
32 | import org.springframework.context.ConfigurableApplicationContext;
33 | import org.springframework.context.annotation.*;
34 |
35 | import java.net.InetSocketAddress;
36 | import java.util.HashMap;
37 | import java.util.Map;
38 | import java.util.Set;
39 |
40 | /**
41 | * Spring Java Configuration and Bootstrap
42 | *
43 | * @author Jibeom Jung
44 | */
45 | @SpringBootApplication
46 | @ComponentScan(basePackages = "com.zbum.example")
47 | @PropertySource(value= "classpath:/properties/local/nettyserver.properties")
48 | public class Application {
49 |
50 | @Configuration
51 | @Profile("production")
52 | @PropertySource("classpath:/properties/production/nettyserver.properties")
53 | static class Production
54 | { }
55 |
56 | @Configuration
57 | @Profile("local")
58 | @PropertySource({"classpath:/properties/local/nettyserver.properties"})
59 | static class Local
60 | { }
61 |
62 | public static void main(String[] args) throws Exception{
63 | ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
64 | ctx.getBean(TCPServer.class).start();
65 | }
66 |
67 | @Value("${tcp.port}")
68 | private int tcpPort;
69 |
70 | @Value("${boss.thread.count}")
71 | private int bossCount;
72 |
73 | @Value("${worker.thread.count}")
74 | private int workerCount;
75 |
76 | @Value("${so.keepalive}")
77 | private boolean keepAlive;
78 |
79 | @Value("${so.backlog}")
80 | private int backlog;
81 |
82 | @SuppressWarnings("unchecked")
83 | @Bean(name = "serverBootstrap")
84 | public ServerBootstrap bootstrap() {
85 | ServerBootstrap b = new ServerBootstrap();
86 | b.group(bossGroup(), workerGroup())
87 | .channel(NioServerSocketChannel.class)
88 | .handler(new LoggingHandler(LogLevel.DEBUG))
89 | .childHandler(somethingChannelInitializer);
90 | Map, Object> tcpChannelOptions = tcpChannelOptions();
91 | Set> keySet = tcpChannelOptions.keySet();
92 | for (@SuppressWarnings("rawtypes") ChannelOption option : keySet) {
93 | b.option(option, tcpChannelOptions.get(option));
94 | }
95 | return b;
96 | }
97 |
98 | @Autowired
99 | @Qualifier("somethingChannelInitializer")
100 | private SomethingChannelInitializer somethingChannelInitializer;
101 |
102 | @Bean(name = "tcpChannelOptions")
103 | public Map, Object> tcpChannelOptions() {
104 | Map, Object> options = new HashMap, Object>();
105 | options.put(ChannelOption.SO_KEEPALIVE, keepAlive);
106 | options.put(ChannelOption.SO_BACKLOG, backlog);
107 | return options;
108 | }
109 |
110 | @Bean(name = "bossGroup", destroyMethod = "shutdownGracefully")
111 | public NioEventLoopGroup bossGroup() {
112 | return new NioEventLoopGroup(bossCount);
113 | }
114 |
115 | @Bean(name = "workerGroup", destroyMethod = "shutdownGracefully")
116 | public NioEventLoopGroup workerGroup() {
117 | return new NioEventLoopGroup(workerCount);
118 | }
119 |
120 | @Bean(name = "tcpSocketAddress")
121 | public InetSocketAddress tcpPort() {
122 | return new InetSocketAddress(tcpPort);
123 | }
124 |
125 | @Bean(name = "channelRepository")
126 | public ChannelRepository channelRepository() {
127 | return new ChannelRepository();
128 | }
129 |
130 | }
--------------------------------------------------------------------------------
/src/main/java/com/zbum/example/socket/server/netty/ChannelRepository.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.zbum.example.socket.server.netty;
17 |
18 | import io.netty.channel.Channel;
19 |
20 | import java.util.HashMap;
21 |
22 | /**
23 | * Channel Repository using HashMap
24 | *
25 | * @author Jibeom Jung
26 | */
27 | public class ChannelRepository {
28 | private HashMap channelCache = new HashMap();
29 |
30 | public ChannelRepository put(String key, Channel value) {
31 | channelCache.put(key, value);
32 | return this;
33 | }
34 |
35 | public Channel get(String key) {
36 | return channelCache.get(key);
37 | }
38 |
39 | public void remove(String key) { this.channelCache.remove(key); }
40 |
41 | public int size() {
42 | return this.channelCache.size();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/zbum/example/socket/server/netty/TCPServer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.zbum.example.socket.server.netty;
17 |
18 | import io.netty.bootstrap.ServerBootstrap;
19 | import io.netty.channel.Channel;
20 | import org.springframework.beans.factory.annotation.Autowired;
21 | import org.springframework.beans.factory.annotation.Qualifier;
22 | import org.springframework.stereotype.Component;
23 |
24 | import javax.annotation.PreDestroy;
25 | import java.net.InetSocketAddress;
26 |
27 |
28 | /**
29 | * Main Server
30 | *
31 | * @author Jibeom Jung
32 | */
33 | @Component
34 | public class TCPServer {
35 |
36 | @Autowired
37 | @Qualifier("serverBootstrap")
38 | private ServerBootstrap serverBootstrap;
39 |
40 | @Autowired
41 | @Qualifier("tcpSocketAddress")
42 | private InetSocketAddress tcpPort;
43 |
44 | private Channel serverChannel;
45 |
46 | public void start() throws Exception {
47 | serverChannel = serverBootstrap.bind(tcpPort).sync().channel().closeFuture().sync().channel();
48 | }
49 |
50 | @PreDestroy
51 | public void stop() throws Exception {
52 | serverChannel.close();
53 | serverChannel.parent().close();
54 | }
55 |
56 | public ServerBootstrap getServerBootstrap() {
57 | return serverBootstrap;
58 | }
59 |
60 | public void setServerBootstrap(ServerBootstrap serverBootstrap) {
61 | this.serverBootstrap = serverBootstrap;
62 | }
63 |
64 | public InetSocketAddress getTcpPort() {
65 | return tcpPort;
66 | }
67 |
68 | public void setTcpPort(InetSocketAddress tcpPort) {
69 | this.tcpPort = tcpPort;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/com/zbum/example/socket/server/netty/handler/SomethingChannelInitializer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.zbum.example.socket.server.netty.handler;
17 |
18 | import io.netty.channel.ChannelInboundHandlerAdapter;
19 | import io.netty.channel.ChannelInitializer;
20 | import io.netty.channel.ChannelPipeline;
21 | import io.netty.channel.socket.SocketChannel;
22 | import io.netty.handler.codec.DelimiterBasedFrameDecoder;
23 | import io.netty.handler.codec.Delimiters;
24 | import io.netty.handler.codec.string.StringDecoder;
25 | import io.netty.handler.codec.string.StringEncoder;
26 | import org.springframework.beans.factory.annotation.Autowired;
27 | import org.springframework.beans.factory.annotation.Qualifier;
28 | import org.springframework.stereotype.Component;
29 |
30 | /**
31 | * Channel Initializer
32 | *
33 | * @author Jibeom Jung
34 | */
35 | @Component
36 | @Qualifier("somethingChannelInitializer")
37 | public class SomethingChannelInitializer extends ChannelInitializer {
38 |
39 | private static final StringDecoder DECODER = new StringDecoder();
40 | private static final StringEncoder ENCODER = new StringEncoder();
41 |
42 | @Autowired
43 | @Qualifier("somethingServerHandler")
44 | private ChannelInboundHandlerAdapter somethingServerHandler;
45 |
46 | @Override
47 | protected void initChannel(SocketChannel socketChannel) throws Exception {
48 | ChannelPipeline pipeline = socketChannel.pipeline();
49 |
50 | // Add the text line codec combination first,
51 | pipeline.addLast(new DelimiterBasedFrameDecoder(1024*1024, Delimiters.lineDelimiter()));
52 | // the encoder and decoder are static as these are sharable
53 | pipeline.addLast(DECODER);
54 | pipeline.addLast(ENCODER);
55 |
56 | pipeline.addLast(somethingServerHandler);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/com/zbum/example/socket/server/netty/handler/SomethingServerHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.zbum.example.socket.server.netty.handler;
17 |
18 | import com.zbum.example.socket.server.netty.ChannelRepository;
19 | import com.zbum.example.socket.server.repository.User;
20 | import com.zbum.example.socket.server.repository.UserRepository;
21 | import io.netty.channel.ChannelHandler;
22 | import io.netty.channel.ChannelHandlerContext;
23 | import io.netty.channel.ChannelInboundHandlerAdapter;
24 | import org.apache.log4j.Logger;
25 | import org.springframework.beans.factory.annotation.Autowired;
26 | import org.springframework.beans.factory.annotation.Qualifier;
27 | import org.springframework.data.domain.Page;
28 | import org.springframework.data.domain.PageRequest;
29 | import org.springframework.data.domain.Sort;
30 | import org.springframework.stereotype.Component;
31 | import org.springframework.util.Assert;
32 |
33 | /**
34 | * event handler to process receiving messages
35 | *
36 | * @author Jibeom Jung
37 | */
38 | @Component
39 | @Qualifier("somethingServerHandler")
40 | @ChannelHandler.Sharable
41 | public class SomethingServerHandler extends ChannelInboundHandlerAdapter {
42 |
43 | @Autowired
44 | private ChannelRepository channelRepository;
45 |
46 | @Autowired
47 | private UserRepository userRepository;
48 |
49 | private static Logger logger = Logger.getLogger(SomethingServerHandler.class.getName());
50 |
51 | @Override
52 | public void channelActive(ChannelHandlerContext ctx) throws Exception {
53 | Assert.notNull(this.channelRepository, "[Assertion failed] - ChannelRepository is required; it must not be null");
54 |
55 | ctx.fireChannelActive();
56 | logger.debug(ctx.channel().remoteAddress());
57 | String channelKey = ctx.channel().remoteAddress().toString();
58 | channelRepository.put(channelKey, ctx.channel());
59 |
60 | ctx.writeAndFlush("Your channel key is " + channelKey + "\n\r");
61 |
62 | logger.debug("Binded Channel Count is " + this.channelRepository.size());
63 | }
64 |
65 | @Override
66 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
67 | String stringMessage = (String) msg;
68 |
69 | logger.debug(stringMessage);
70 |
71 | if ( stringMessage.startsWith("name?")) {
72 | String searchKeyword = stringMessage.substring(5, stringMessage.length());
73 | logger.debug("searchKeyword is " + searchKeyword);
74 |
75 | if ( searchKeyword.equalsIgnoreCase("all")) {
76 | Page userlist = userRepository.findByUseYn(true,new PageRequest(0, 1000, new Sort(Sort.Direction.ASC, "id")));
77 | for (User user :userlist) {
78 | ctx.channel().writeAndFlush(user.getUsername()+":"+ user.getPhoneNumber() + "\n\r");
79 | }
80 |
81 | return;
82 | }
83 |
84 | User user = userRepository.findByUsername(searchKeyword);
85 | if ( user == null ) {
86 | ctx.channel().writeAndFlush("There is no user named " + searchKeyword + "\n\r");
87 | }else {
88 | ctx.channel().writeAndFlush(user.getPhoneNumber() + "\n\r");
89 | }
90 |
91 | return;
92 | }
93 |
94 | String[] splitMessage = stringMessage.split("::");
95 |
96 | if ( splitMessage.length != 2 ) {
97 | ctx.channel().writeAndFlush(stringMessage + "\n\r");
98 | return;
99 | }
100 |
101 | if ( channelRepository.get(splitMessage[0]) != null ) {
102 | channelRepository.get(splitMessage[0]).writeAndFlush(splitMessage[1] + "\n\r");
103 | }
104 |
105 |
106 | }
107 |
108 | @Override
109 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
110 | logger.error(cause.getMessage(), cause);
111 | //ctx.close();
112 | }
113 |
114 | @Override
115 | public void channelInactive(ChannelHandlerContext ctx){
116 | Assert.notNull(this.channelRepository, "[Assertion failed] - ChannelRepository is required; it must not be null");
117 | Assert.notNull(ctx);
118 |
119 | String channelKey = ctx.channel().remoteAddress().toString();
120 | this.channelRepository.remove(channelKey);
121 |
122 | logger.debug("Binded Channel Count is " + this.channelRepository.size());
123 | }
124 |
125 | public void setChannelRepository(ChannelRepository channelRepository) {
126 | this.channelRepository = channelRepository;
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/src/main/java/com/zbum/example/socket/server/repository/RepositoryConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.zbum.example.socket.server.repository;
17 |
18 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
19 | import org.springframework.context.annotation.Configuration;
20 | import org.springframework.context.annotation.Profile;
21 | import org.springframework.context.annotation.PropertySource;
22 |
23 | /**
24 | *
25 | * @author Jibeom Jung
26 | */
27 | @Configuration
28 | @EnableAutoConfiguration
29 | @PropertySource({"classpath:/properties/local/springjpa.properties"})
30 | public class RepositoryConfiguration {
31 | @Configuration
32 | @Profile("production")
33 | @PropertySource("classpath:/properties/production/springjpa.properties")
34 | static class Production
35 | { }
36 |
37 | @Configuration
38 | @Profile("local")
39 | @PropertySource({"classpath:/properties/local/springjpa.properties"})
40 | static class Local
41 | { }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/zbum/example/socket/server/repository/User.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.zbum.example.socket.server.repository;
17 |
18 | import org.springframework.data.jpa.domain.AbstractPersistable;
19 |
20 | import javax.persistence.Column;
21 | import javax.persistence.Entity;
22 | import javax.persistence.Table;
23 |
24 | /**
25 | * @author Jibeom Jung
26 | */
27 | @Entity
28 | @Table(name="user")
29 | //@NamedQuery(name="User.findByTheUsername", query = "from User u where u.username=?1")
30 | public class User extends AbstractPersistable {
31 |
32 | @Column(unique=true)
33 | private String username;
34 |
35 | @Column(name="phone_number")
36 | private String phoneNumber;
37 |
38 | @Column(name="use_yn")
39 | private Boolean useYn;
40 |
41 | public User(){
42 | this(null);
43 | }
44 |
45 | public User(Long id) {
46 | this.setId(id);
47 | }
48 |
49 | public String getUsername() {
50 | return username;
51 | }
52 |
53 | public void setUsername(String username) {
54 | this.username = username;
55 | }
56 |
57 | public String getPhoneNumber() {
58 | return phoneNumber;
59 | }
60 |
61 | public void setPhoneNumber(String phoneNumber) {
62 | this.phoneNumber = phoneNumber;
63 | }
64 |
65 | public Boolean getUseYn() {
66 | return useYn;
67 | }
68 |
69 | public void setUseYn(Boolean useYn) {
70 | this.useYn = useYn;
71 | }
72 |
73 | @Override
74 | public String toString() {
75 | return "User{" +
76 | "username='" + username + '\'' +
77 | ", phoneNumber='" + phoneNumber + '\'' +
78 | ", useYn=" + useYn +
79 | '}';
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/com/zbum/example/socket/server/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.zbum.example.socket.server.repository;
17 |
18 | import org.springframework.data.domain.Page;
19 | import org.springframework.data.domain.Pageable;
20 | import org.springframework.data.repository.PagingAndSortingRepository;
21 |
22 | /**
23 | * @author Jibeom Jung
24 | */
25 | public interface UserRepository extends PagingAndSortingRepository {
26 |
27 | /**
28 | *
29 | * @param username
30 | * @return
31 | */
32 | User findByUsername(String username);
33 |
34 | Page findAll(Pageable pageable);
35 |
36 | Page findByUseYn(Boolean useYn, Pageable pageable);
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main/resources/properties.production/nettyserver.properties:
--------------------------------------------------------------------------------
1 | tcp.port=8090
2 | boss.thread.count=2
3 | worker.thread.count=2
4 | so.keepalive=true
5 | so.backlog=100
--------------------------------------------------------------------------------
/src/main/resources/properties.production/springjpa.properties:
--------------------------------------------------------------------------------
1 | spring.datasource.url=jdbc:h2:~/h2test
2 | spring.datasource.username=sa
3 | spring.datasource.password=
4 | spring.datasource.driver-class-name=org.h2.Driver
5 |
6 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
7 | spring.jpa.show-sql=true
8 | spring.jpa.hibernate.ddl-auto=create
--------------------------------------------------------------------------------
/src/main/resources/properties/local/nettyserver.properties:
--------------------------------------------------------------------------------
1 | tcp.port=8090
2 | boss.thread.count=2
3 | worker.thread.count=2
4 | so.keepalive=true
5 | so.backlog=100
6 |
7 |
--------------------------------------------------------------------------------
/src/main/resources/properties/local/springjpa.properties:
--------------------------------------------------------------------------------
1 | spring.datasource.url=jdbc:h2:~/h2test
2 | spring.datasource.username=sa
3 | spring.datasource.password=
4 | spring.datasource.driver-class-name=org.h2.Driver
5 |
6 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
7 | spring.jpa.show-sql=true
8 | spring.jpa.hibernate.ddl-auto=validate
--------------------------------------------------------------------------------
/src/test/java/com/zbum/example/socket/server/netty/handler/SomethingServerHandlerTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.zbum.example.socket.server.netty.handler;
17 |
18 | import com.zbum.example.socket.server.netty.ChannelRepository;
19 | import io.netty.channel.Channel;
20 | import io.netty.channel.ChannelHandlerContext;
21 | import org.junit.After;
22 | import org.junit.Before;
23 | import org.junit.Test;
24 |
25 | import java.net.SocketAddress;
26 |
27 | import static org.mockito.Mockito.mock;
28 | import static org.mockito.Mockito.when;
29 |
30 | /**
31 | * Test for SomethingServerHandler.java
32 | *
33 | * @author Jibeom Jung
34 | */
35 | public class SomethingServerHandlerTest {
36 |
37 | private SomethingServerHandler somethingServerHandler;
38 |
39 | private ChannelHandlerContext channelHandlerContext;
40 |
41 | private Channel channel;
42 |
43 | private SocketAddress remoteAddress;
44 |
45 | @Before
46 | public void setUp() throws Exception {
47 | somethingServerHandler = new SomethingServerHandler();
48 | somethingServerHandler.setChannelRepository(new ChannelRepository());
49 |
50 | channelHandlerContext = mock(ChannelHandlerContext.class);
51 | channel = mock(Channel.class);
52 | remoteAddress = mock(SocketAddress.class);
53 | }
54 |
55 | @After
56 | public void tearDown() throws Exception {
57 |
58 | }
59 |
60 | @Test
61 | public void testChannelActive() throws Exception {
62 | when(channelHandlerContext.channel()).thenReturn(channel);
63 | when(channelHandlerContext.channel().remoteAddress()).thenReturn(remoteAddress);
64 | somethingServerHandler.channelActive(channelHandlerContext);
65 | }
66 |
67 | @Test
68 | public void testChannelRead() throws Exception {
69 | when(channelHandlerContext.channel()).thenReturn(channel);
70 | somethingServerHandler.channelRead(channelHandlerContext, "test message");
71 | }
72 |
73 | @Test
74 | public void testExceptionCaught() throws Exception {
75 |
76 | }
77 | }
--------------------------------------------------------------------------------
/src/test/java/com/zbum/example/socket/server/repository/UserRepositoryTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.zbum.example.socket.server.repository;
17 |
18 | import org.junit.After;
19 | import org.junit.Before;
20 | import org.junit.Test;
21 | import org.junit.runner.RunWith;
22 | import org.springframework.beans.factory.annotation.Autowired;
23 | import org.springframework.test.context.ContextConfiguration;
24 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
25 | import org.springframework.test.context.transaction.TransactionConfiguration;
26 | import org.springframework.transaction.annotation.Transactional;
27 |
28 | import static org.junit.Assert.assertEquals;
29 |
30 | /**
31 | * Test for SomethingServerHandler.java
32 | *
33 | * @author Jibeom Jung
34 | */
35 | @RunWith(SpringJUnit4ClassRunner.class)
36 | @ContextConfiguration(classes = {RepositoryConfiguration.class})
37 | @TransactionConfiguration(defaultRollback = false)
38 | @Transactional
39 | public class UserRepositoryTest {
40 |
41 | @Autowired
42 | private UserRepository userRepository;
43 |
44 | @Before
45 | public void setUp() throws Exception {
46 |
47 | }
48 |
49 | @After
50 | public void tearDown() throws Exception {
51 |
52 | }
53 |
54 | @Test
55 | public void testFindByTheUsername() throws Exception {
56 |
57 | }
58 |
59 | @Test
60 | public void testSave() throws Exception {
61 | User user = new User(1L);
62 | user.setUsername("zbum");
63 | user.setPhoneNumber("010-1111-2222");
64 | user.setUseYn(true);
65 | userRepository.save(user);
66 |
67 | User userRepositoryByTheUsername = userRepository.findByUsername("zbum");
68 | assertEquals(userRepositoryByTheUsername.getPhoneNumber(), "010-1111-2222");
69 |
70 | }
71 | }
--------------------------------------------------------------------------------