Top Banner
http://www.flickr.com/photos/jox1989/5327951306 おっぴろげ JavaEE DevOps
65
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: おっぴろげJavaEE DevOps

http://www.flickr.com/photos/jox1989/5327951306

おっぴろげ JavaEE DevOps

Page 2: おっぴろげJavaEE DevOps

おっぴろげ is 何

Page 3: おっぴろげJavaEE DevOps

でもJavaEEの導入事例って あんま聞かなくない?

http://www.flickr.com/photos/dogwelder/94393980

Page 4: おっぴろげJavaEE DevOps

せっかく作ったんだし シガラミがないうちに 全部話してしまえー

http://www.flickr.com/photos/pmillera4/8914149268

Page 5: おっぴろげJavaEE DevOps

永瀬 泰一郎 グリー株式会社

@nagaseyasuhito

Page 6: おっぴろげJavaEE DevOps

http://builder.japan.zdnet.com/sp_oracle/weblogic_2013/35040464/

Page 7: おっぴろげJavaEE DevOps

meets

Page 8: おっぴろげJavaEE DevOps

Scalaでやろうぜ!

Page 9: おっぴろげJavaEE DevOps

やっぱ別チーム行くわ!ノシ

Page 10: おっぴろげJavaEE DevOps

JavaEEやるチャンスや!

Page 11: おっぴろげJavaEE DevOps

ひとりDevOps

http://www.flickr.com/photos/nanophoto69/5294068212

Page 12: おっぴろげJavaEE DevOps

開発 テスト

リリース&デプロイ 運用

Page 13: おっぴろげJavaEE DevOps

椿http://bit.ly/jjug-camellia

Page 14: おっぴろげJavaEE DevOps

開発するぞ

Page 15: おっぴろげJavaEE DevOps

Overviewhttp://www.flickr.com/photos/codlibrary/2282696252

EJB Timer

JMSCDI

JAX-RS

JPA

Page 16: おっぴろげJavaEE DevOps

Abstract Entity

@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;! @Column(nullable = false) @Temporal(TemporalType.TIMESTAMP) @XmlJavaTypeAdapter(ISO8601DateAdapter.class) private Date createdAt;}

LombokJPA JAXB

Page 17: おっぴろげJavaEE DevOps

Xml Adapter

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()); }}

LombokJPA JAXB

Page 18: おっぴろげJavaEE DevOps

Concrete Entity

@Entity@Setter @Getterpublic class User extends BaseEntity { @Column(nullable = false, unique = true) @Pattern(regexp = "[\\p{Alnum}]*") private String name;! @Column(nullable = false) @XmlTransient private String password;}

Bean ValidationLombokJPA JAXB

Page 19: おっぴろげJavaEE DevOps

Abstract Dao

public interface Query<T> { CriteriaQuery<T> execute( CriteriaBuilder b, CriteriaQuery<T> q, Root<T> r);}

JPA

Page 20: おっぴろげJavaEE DevOps

Abstract Dao

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());! return this.entityManager.createQuery( query.execute(b, q, r)).getSingleResult(); }! protected abstract Class<T> getEntityClass();}

JPA

Page 21: おっぴろげJavaEE DevOps

Concrete Dao

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) {! return q.select(r). where(b.equal(r.get(User_.name), name)); } }); }}

JPA

Page 22: おっぴろげJavaEE DevOps

Concrete Dao

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)); }}

Page 23: おっぴろげJavaEE DevOps

Service

@Transactionalpublic 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); }}

Bean ValidationCDI

Page 24: おっぴろげJavaEE DevOps

JAX-RS

@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); }}

CDIJAX-RS

Page 25: おっぴろげJavaEE DevOps

テストするぞ

http://www.flickr.com/photos/mattt_org/2831690932

Page 26: おっぴろげJavaEE DevOps

Separate UT and IT

どう分けるか

Page 27: おっぴろげJavaEE DevOps

Integration Test

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <executions> <execution> <goals> <goal>integration-test</goal> </goals> </execution> </executions></plugin>

Page 28: おっぴろげJavaEE DevOps

Integration Test

mvn verify

Page 29: おっぴろげJavaEE DevOps

Unit Test

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <excludes> <exclude>**/*IT.java</exclude> </excludes> </configuration></plugin>

Page 30: おっぴろげJavaEE DevOps

Unit Test

mvn test

Page 31: おっぴろげJavaEE DevOps

Preparing Entity

Manager

<persistence> <persistence-unit name="camellia" transaction-type="JTA">! <jta-data-source>jdbc/camellia</jta-data-source>! <exclude-unlisted-classes> false </exclude-unlisted-classes>! <properties> <property name="eclipselink.ddl-generation" value="create-tables" /> </properties>! </persistence-unit></persistence>

Page 32: おっぴろげJavaEE DevOps

Preparing Entity

Manager

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:");!EntityManagerFactory entityManagerFactory = Persistence. createEntityManagerFactory("camellia", prop);!EntityManager entityManager = entityManagerFactory.createEntityManager();

JPA

Page 33: おっぴろげJavaEE DevOps

Concrete Dao Test

public class UserDaoTest extends BaseDaoTest { private FixtureHelper fixtureHelper = new FixtureHelper();! private UserDao userDao = new UserDao();! @Before public void before() throws Throwable { Deencapsulation.setField(this.fixtureHelper, this.getEntityManager());! Deencapsulation.setField(this.userDao, this.getEntityManager()); }

JUnit JMockit

Page 34: おっぴろげJavaEE DevOps

Concrete Dao Test

@Test public void findByNameSuccess() { this.fixtureHelper. createUser("user", "password");! assertThat( this.userDao.findByName("user”).getName(), is("user")); }}

JUnit

Page 35: おっぴろげJavaEE DevOps

Abstract Integration

Test

@RunWith(Arquillian.class)public abstract class BaseServiceIT {! @Deployment public static Archive<?> createDeployment() { WebArchive war = ShrinkWrap.create(WebArchive.class);! war.addPackages(true, Root.class.getPackage()); war.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); war.addAsResource("META-INF/persistence.xml");! return war; }}

ArquillianJUnit

Page 36: おっぴろげJavaEE DevOps

Concrete Integration

Test

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())); }! @Test(expected = TransactionalException.class) public void createFailureByDuplicatedName() { this.userService.create("duplicated user","password"); this.userService.create("duplicated user","password"); }}

CDIJUnit

Page 37: おっぴろげJavaEE DevOps

リリース&デプロイするぞ

http://www.flickr.com/photos/ivyfield/4763965911

Page 38: おっぴろげJavaEE DevOps

Release and

Versionリリースとバージョン

Page 39: おっぴろげJavaEE DevOps

maven release plugin

<scm> <url>https://github.com/nagaseyasuhito/camellia</url> <connection> scm:git:[email protected]:nagaseyasuhito/camellia.git </connection> <tag>HEAD</tag></scm>!<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>

Page 40: おっぴろげJavaEE DevOps

maven release plugin

mvn release:prepare release:perform

Page 41: おっぴろげJavaEE DevOps

Jenkins Build

Pipeline Plugin

Unit Test

Integration Test Release

Production Deploy

Staging Deploy

Development Deploy

Page 42: おっぴろげJavaEE DevOps

Clone workspace

SCM Plugin

GitHub

Clone workspace SCM

Unit Test

Integration Test

Page 43: おっぴろげJavaEE DevOps

Deploy to

GlassFish

camellia

das.camellia camellia:1.0.0

as1.camellia camellia:1.0.0

as2.camellia camellia:1.0.0

Reverse Proxy

Production Deploy

通常時

Page 44: おっぴろげJavaEE DevOps

Deploy to

GlassFish

camellia

das.camellia camellia:1.0.0 camellia:1.0.1

as1.camellia camellia:1.0.0

as2.camellia camellia:1.0.0

Reverse Proxy

Production Deploy

asadmin deploy --target=camellia --enabled=false --name camellia:1.0.1 /tmp/camellia:1.0.1.war

Page 45: おっぴろげJavaEE DevOps

Deploy to

GlassFish

camellia

das.camellia camellia:1.0.0 camellia:1.0.1

as1.camellia camellia:1.0.0

as2.camellia camellia:1.0.0

Reverse Proxy

Production Deploy

リバースプロキシからas1.camelliaを抜く

Page 46: おっぴろげJavaEE DevOps

Deploy to

GlassFish

camellia

das.camellia camellia:1.0.0 camellia:1.0.1

as1.camellia camellia:1.0.1

as2.camellia camellia:1.0.0

Reverse Proxy

Production Deploy

asadmin enable --target=as1.camellia camellia:1.0.1

Page 47: おっぴろげJavaEE DevOps

Deploy to

GlassFish

camellia

das.camellia camellia:1.0.0 camellia:1.0.1

as1.camellia camellia:1.0.1

as2.camellia camellia:1.0.0

Reverse Proxy

Production Deploy

リバースプロキシにas1.camelliaを入れる

Page 48: おっぴろげJavaEE DevOps

Deploy to

GlassFish

camellia

das.camellia camellia:1.0.0 camellia:1.0.1

as1.camellia camellia:1.0.1

as2.camellia camellia:1.0.0

Reverse Proxy

Production Deploy

リバースプロキシからas2.camelliaを抜く

Page 49: おっぴろげJavaEE DevOps

Deploy to

GlassFish

camellia

das.camellia camellia:1.0.0 camellia:1.0.1

as1.camellia camellia:1.0.1

as2.camellia camellia:1.0.1

Reverse Proxy

Production Deploy

asadmin enable --target=as2.camellia camellia:1.0.1

Page 50: おっぴろげJavaEE DevOps

Deploy to

GlassFish

camellia

das.camellia camellia:1.0.0 camellia:1.0.1

as1.camellia camellia:1.0.1

as2.camellia camellia:1.0.1

Reverse Proxy

Production Deploy

リバースプロキシにas2.camelliaを入れる

Page 51: おっぴろげJavaEE DevOps

運用するぞ

http://www.flickr.com/photos/defenceimages/6331498981

Page 52: おっぴろげJavaEE DevOps

logging

asadmin set-log-levels org.eclipse.persistence.session=FINE

Page 53: おっぴろげJavaEE DevOps

logging

[#|2013-11-23T21:37:11.979+0900|INFO|glassfish 4.0|javax.enterprise.system.core|_ThreadID=101;_ThreadName=Thread-16;_TimeMillis=1385210231979;_LevelValue=800;_MessageID=NCLS-CORE-00022;| Loading application __admingui done in 6,277 ms|#]

[2013-11-23T21:39:41.869+0900] [glassfish 4.0] [INFO] [NCLS-CORE-00022] [javax.enterprise.system.core] [tid: _ThreadID=100 _ThreadName=Thread-16] [timeMillis: 1385210381869] [levelValue: 800] [[ Loading application __admingui done in 5,286 ms]]

com.sun.enterprise.server.logging.UniformLogFormatter

com.sun.enterprise.server.logging.ODLLogFormatter

Page 54: おっぴろげJavaEE DevOps

JMX

@MXBeanpublic interface UserMonitor { long getNumberOfUsers();}

JMX

Page 55: おっぴろげJavaEE DevOps

JMX

@Startup @Singletonpublic 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(); }}

LombokJMX EJB CDI

Page 56: おっぴろげJavaEE DevOps
Page 57: おっぴろげJavaEE DevOps

Demoデモしたい

Page 58: おっぴろげJavaEE DevOps

Gangliaで出したい

Page 59: おっぴろげJavaEE DevOps
Page 60: おっぴろげJavaEE DevOps

jmetric

asadmin create-jvm-options '-javaagent\: ${com.sun.aas.instanceRoot}/lib/jmxetric-1.0.4.jar= config=${com.sun.aas.instanceRoot}/config/jmxetric.xml'

Page 61: おっぴろげJavaEE DevOps

jmetric

<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>

Page 62: おっぴろげJavaEE DevOps

まとめ

Page 63: おっぴろげJavaEE DevOps

Conclusionエンタープライズ言うな

Page 64: おっぴろげJavaEE DevOps

Copyright © GREE, Inc. All Rights Reserved.

インターネットを通じて、世界をより良くする。

Page 65: おっぴろげJavaEE DevOps

Copyright © GREE, Inc. All Rights Reserved.