おっぴろげJavaEE DevOps

30,098 views

Published on

Published in: Technology
0 Comments
23 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
30,098
On SlideShare
0
From Embeds
0
Number of Embeds
12,745
Actions
Shares
0
Downloads
50
Comments
0
Likes
23
Embeds 0
No embeds

No notes for slide

おっぴろげJavaEE DevOps

  1. 1. http://www.flickr.com/photos/jox1989/5327951306 おっぴろげ JavaEE DevOps
  2. 2. おっぴろげ is 何
  3. 3. でもJavaEEの導入事例って あんま聞かなくない? http://www.flickr.com/photos/dogwelder/94393980
  4. 4. せっかく作ったんだし シガラミがないうちに 全部話してしまえー http://www.flickr.com/photos/pmillera4/8914149268
  5. 5. 永瀬 泰一郎 グリー株式会社 @nagaseyasuhito
  6. 6. http://builder.japan.zdnet.com/sp_oracle/weblogic_2013/35040464/
  7. 7. meets
  8. 8. Scalaでやろうぜ!
  9. 9. やっぱ別チーム行くわ!ノシ
  10. 10. JavaEEやるチャンスや!
  11. 11. ひとりDevOps http://www.flickr.com/photos/nanophoto69/5294068212
  12. 12. 開発 テスト リリース&デプロイ 運用
  13. 13. 椿 http://bit.ly/jjug-camellia
  14. 14. 開発するぞ
  15. 15. JAX-RS EJB Timer CDI JMS JPA Overview http://www.flickr.com/photos/codlibrary/2282696252
  16. 16. JPA Lombok JAXB @MappedSuperclass @Setter @Getter @EqualsAndHashCode(of = { "id" }) public abstract class BaseEntity { @Id @GeneratedValue(strategy = IDENTITY) private Long id; ! ! } @Column(nullable = false) @Version @XmlTransient private Long version; Abstract Entity @Column(nullable = false) @Temporal(TemporalType.TIMESTAMP) @XmlJavaTypeAdapter(ISO8601DateAdapter.class) private Date createdAt;
  17. 17. JPA Lombok JAXB public class ISO8601DateAdapter extends XmlAdapter<String, Date> { ! @Override public Date unmarshal(String v) throws Exception { return new Date(ISODateTimeFormat. dateTimeNoMillis().withZoneUTC().parseMillis(v)); } ! @Override public String marshal(Date v) throws Exception { return ISODateTimeFormat. dateTimeNoMillis().withZoneUTC().print(v.getTime()); } } Xml Adapter
  18. 18. JPA Lombok JAXB Bean Validation @Entity @Setter @Getter public class User extends BaseEntity { @Column(nullable = false, unique = true) @Pattern(regexp = "[p{Alnum}]*") private String name; ! @Column(nullable = false) @XmlTransient private String password; } Concrete Entity
  19. 19. JPA public interface Query<T> { CriteriaQuery<T> execute( CriteriaBuilder b, CriteriaQuery<T> q, Root<T> r); } Abstract Dao
  20. 20. JPA public abstract class BaseDao<T> { protected T getSingleResult(Query<T> query) { CriteriaBuilder b = this.entityManager.getCriteriaBuilder(); ! CriteriaQuery<T> q = b.createQuery(this.getEntityClass()); ! Root<T> r = q.from(this.getEntityClass()); ! Abstract Dao return this.entityManager.createQuery( query.execute(b, q, r)).getSingleResult(); } ! protected abstract Class<T> getEntityClass(); }
  21. 21. JPA public class UserDao extends BaseDao<User> { ! ! } public User findByName(final String name) { return this.getSingleResult(new Query<User>() { @Override public CriteriaQuery<User> execute( CriteriaBuilder b, CriteriaQuery<User> q, Root<User> r) { Concrete Dao return q.select(r). where(b.equal(r.get(User_.name), name)); } }); }
  22. 22. public class UserDao extends BaseDao<User> { ! } public User findByName(String name) { return this.getSingleResult((b, q, r) -> q.select(r).where(b.equal(r.get(User_.name), name)); } Concrete Dao
  23. 23. CDI Bean Validation @Transactional public class UserService { @Inject private UserDao userDao; ! public User create(@NotNull String name) { User user = new User(name); this.userDao.persist(user); ! return user; } ! public User show(@NotNull String name) { return this.userDao.findByName(name); } } Service
  24. 24. JAX-RS CDI @Path("user") public class UserResource { @Inject private UserService userService; ! @Path("{name}") // PUT /user/{name} @PUT public User create(@PathParam("name") String name) { return this.userService.create(name); } ! } @Path(“{name}") // GET /user/{name} @GET public User show(@PathParam("name") String name) { return this.userService.show(name); } JAX-RS
  25. 25. テストするぞ http://www.flickr.com/photos/mattt_org/2831690932
  26. 26. Separate UT and IT どう分けるか
  27. 27. <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <executions> <execution> <goals> <goal>integration-test</goal> </goals> </execution> </executions> </plugin> Integration Test
  28. 28. mvn verify Integration Test
  29. 29. <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <excludes> <exclude>**/*IT.java</exclude> </excludes> </configuration> </plugin> Unit Test
  30. 30. mvn test Unit Test
  31. 31. <persistence> <persistence-unit name="camellia" transaction-type="JTA"> ! <jta-data-source>jdbc/camellia</jta-data-source> ! <exclude-unlisted-classes> false </exclude-unlisted-classes> ! ! Preparing Entity Manager <properties> <property name="eclipselink.ddl-generation" value="create-tables" /> </properties> </persistence-unit> </persistence>
  32. 32. JPA Map<String, String> prop = Maps.newHashMap(); ! prop.put("javax.persistence.transactionType", "RESOURCE_LOCAL"); prop.put("javax.persistence.jtaDataSource", ""); prop.put("javax.persistence.jdbc.driver", "org.h2.Driver"); prop.put("javax.persistence.jdbc.url", "jdbc:h2:mem:"); ! Preparing Entity Manager EntityManagerFactory entityManagerFactory = Persistence. createEntityManagerFactory("camellia", prop); ! EntityManager entityManager = entityManagerFactory.createEntityManager();
  33. 33. JUnit JMockit public class UserDaoTest extends BaseDaoTest { private FixtureHelper fixtureHelper = new FixtureHelper(); ! private UserDao userDao = new UserDao(); ! ! Concrete Dao Test @Before public void before() throws Throwable { Deencapsulation.setField(this.fixtureHelper, this.getEntityManager()); Deencapsulation.setField(this.userDao, this.getEntityManager()); }
  34. 34. JUnit @Test public void findByNameSuccess() { this.fixtureHelper. createUser("user", "password"); ! } assertThat( this.userDao.findByName("user”).getName(), is("user")); } Concrete Dao Test
  35. 35. JUnit Arquillian @RunWith(Arquillian.class) public abstract class BaseServiceIT { ! @Deployment public static Archive<?> createDeployment() { WebArchive war = ShrinkWrap.create(WebArchive.class); ! ! Abstract Integration Test war.addPackages(true, Root.class.getPackage()); war.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); war.addAsResource("META-INF/persistence.xml"); return war; } }
  36. 36. JUnit CDI public class UserServiceIT extends BaseServiceIT { @Inject private FixtureHelper fixtureHelper; @Inject private UserService userService; ! ! } @Test public void createSuccess() { assertThat( this.userService.create("create user", "password"), is(notNullValue())); } Concrete Integration Test @Test(expected = TransactionalException.class) public void createFailureByDuplicatedName() { this.userService.create("duplicated user","password"); this.userService.create("duplicated user","password"); }
  37. 37. リリース&デプロイするぞ http://www.flickr.com/photos/ivyfield/4763965911
  38. 38. Release and Version リリースとバージョン
  39. 39. <scm> <url>https://github.com/nagaseyasuhito/camellia</url> <connection> scm:git:git@github.com:nagaseyasuhito/camellia.git </connection> <tag>HEAD</tag> </scm> ! maven release plugin <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-release-plugin</artifactId> <configuration> <tagNameFormat>@{project.version}</tagNameFormat> <goals>package</goals> </configuration> </plugin> </plugins> </build>
  40. 40. maven release plugin mvn release:prepare release:perform
  41. 41. Unit Test Integration Test Development Deploy Jenkins Build Pipeline Plugin Release Staging Deploy Production Deploy
  42. 42. GitHub Clone workspace SCM Plugin Unit Test Clone workspace SCM Integration Test
  43. 43. 通常時 Production Deploy das.camellia camellia:1.0.0 Deploy to GlassFish camellia as1.camellia camellia:1.0.0 as2.camellia camellia:1.0.0 Reverse Proxy
  44. 44. asadmin deploy --target=camellia --enabled=false --name camellia:1.0.1 /tmp/camellia:1.0.1.war Production Deploy das.camellia camellia:1.0.0 camellia:1.0.1 Deploy to GlassFish camellia as1.camellia camellia:1.0.0 as2.camellia camellia:1.0.0 Reverse Proxy
  45. 45. リバースプロキシからas1.camelliaを抜く Production Deploy das.camellia camellia:1.0.0 camellia:1.0.1 Deploy to GlassFish camellia as1.camellia camellia:1.0.0 as2.camellia camellia:1.0.0 Reverse Proxy
  46. 46. asadmin enable --target=as1.camellia camellia:1.0.1 Production Deploy das.camellia camellia:1.0.0 camellia:1.0.1 Deploy to GlassFish camellia as1.camellia camellia:1.0.1 as2.camellia camellia:1.0.0 Reverse Proxy
  47. 47. リバースプロキシにas1.camelliaを入れる Production Deploy das.camellia camellia:1.0.0 camellia:1.0.1 Deploy to GlassFish camellia as1.camellia camellia:1.0.1 as2.camellia camellia:1.0.0 Reverse Proxy
  48. 48. リバースプロキシからas2.camelliaを抜く Production Deploy das.camellia camellia:1.0.0 camellia:1.0.1 Deploy to GlassFish camellia as1.camellia camellia:1.0.1 as2.camellia camellia:1.0.0 Reverse Proxy
  49. 49. asadmin enable --target=as2.camellia camellia:1.0.1 Production Deploy das.camellia camellia:1.0.0 camellia:1.0.1 Deploy to GlassFish camellia as1.camellia camellia:1.0.1 as2.camellia camellia:1.0.1 Reverse Proxy
  50. 50. リバースプロキシにas2.camelliaを入れる Production Deploy das.camellia camellia:1.0.0 camellia:1.0.1 Deploy to GlassFish camellia as1.camellia camellia:1.0.1 as2.camellia camellia:1.0.1 Reverse Proxy
  51. 51. http://www.flickr.com/photos/defenceimages/6331498981 運用するぞ
  52. 52. asadmin set-log-levels org.eclipse.persistence.session=FINE logging
  53. 53. com.sun.enterprise.server.logging.UniformLogFormatter [#|2013-11-23T21:37:11.979+0900|INFO|glassfish 4.0| javax.enterprise.system.core| _ThreadID=101;_ThreadName=Thread-16;_TimeMillis=1385210231979;_Level Value=800;_MessageID=NCLS-CORE-00022;| Loading application __admingui done in 6,277 ms|#] com.sun.enterprise.server.logging.ODLLogFormatter [2013-11-23T21:39:41.869+0900] [glassfish 4.0] [INFO] [NCLSCORE-00022] [javax.enterprise.system.core] [tid: _ThreadID=100 _ThreadName=Thread-16] [timeMillis: 1385210381869] [levelValue: 800] [[ Loading application __admingui done in 5,286 ms]] logging
  54. 54. JMX @MXBean public interface UserMonitor { long getNumberOfUsers(); } JMX
  55. 55. JMX Lombok EJB CDI @Startup @Singleton public class UserMonitorImpl implements UserMonitor { @Inject private UserDao userDao; ! @SneakyThrows @PostConstruct public void initialize() { ObjectName objectName = new ObjectName("Camellia:type=User"); MBeanServer server = ManagementFactory.getPlatformMBeanServer() if (server.isRegistered(objectName)) { server.unregisterMBean(objectName); } server.registerMBean(this, objectName); } ! @Override public long getNumberOfUsers() { return this.userDao.count(); } } JMX
  56. 56. デモしたい Demo
  57. 57. Gangliaで出したい
  58. 58. asadmin create-jvm-options '-javaagent: ${com.sun.aas.instanceRoot}/lib/jmxetric-1.0.4.jar= config=${com.sun.aas.instanceRoot}/config/jmxetric.xml' jmetric
  59. 59. <jmxetric-config> <jvm process="Camellia" /> ! <sample delay="300"> <mbean name="Camellia:type=User" pname="User"> <attribute name="NumberOfUsers" type="int16" /> </mbean> </sample> ! <ganglia hostname="localhost" port="8649" mode="multicast" wireformat31x="true" /> </jmxetric-config> jmetric
  60. 60. まとめ
  61. 61. エンタープライズ言うな Conclusion
  62. 62. インターネットを通じて、
 世界をより良くする。 Copyright © GREE, Inc. All Rights Reserved.
  63. 63. Copyright © GREE, Inc. All Rights Reserved.

×