Java tutorial
/* * Copyright (C) 2017 FormKiQ Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.formkiq.core.equifax.service; import static com.formkiq.core.equifax.service.EquifaxCreditCheckRequestType.CACHED; import static com.formkiq.core.equifax.service.EquifaxCreditCheckRequestType.ERROR; import static com.formkiq.core.equifax.service.EquifaxCreditCheckRequestType.NEW; import static com.formkiq.core.form.FormFinder.findValueByKey; import static com.formkiq.core.util.Strings.extractLabelAndValue; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Optional; import java.util.UUID; import javax.persistence.EntityManager; import javax.persistence.Query; import org.apache.commons.lang3.math.NumberUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; import com.formkiq.core.form.dto.FormJSON; import com.formkiq.core.form.dto.FormJSONField; import com.formkiq.core.util.DateService; /** * Equifax Services Implementation. * */ public class EquifaxServiceImpl implements EquifaxService { /** {@link EntityManager}. */ private EntityManager em; /** {@link DateService}. */ @Autowired private DateService dateService; /** TransactionManager. */ @Autowired private PlatformTransactionManager transactionManager; /** * constructor. * @param entityManager {@link EntityManager} */ public EquifaxServiceImpl(final EntityManager entityManager) { this.em = entityManager; } @Override public List<EquifaxCreditCheck> findAll(final Date start, final Date end) { String sql = "select e.request, e.response, e.request_type, " + " e.url, e.requester, e.inserted_date " + "from equifax_credit_checks e " + " where e.inserted_date between :start and :end" + " order by inserted_date desc"; Calendar c = Calendar.getInstance(); c.setTime(end); c.add(Calendar.DAY_OF_MONTH, 1); Query query = this.em.createNativeQuery(sql).setParameter("start", this.dateService.removeTime(start)) .setParameter("end", this.dateService.removeTime(c.getTime())); return transform(query); } @Override public EquifaxCreditCheck getCachedResponse(final String request, final Date date) { String sql = "select e.request, e.response, e.request_type, " + " e.url, e.requester, e.inserted_date " + "from equifax_credit_checks e " + " where e.request=:request and e.inserted_date >= :date " + " order by inserted_date desc"; Query query = this.em.createNativeQuery(sql).setParameter("request", request).setParameter("date", date); List<EquifaxCreditCheck> results = transform(query); return !results.isEmpty() ? results.get(0) : null; } /** * Get Equifax Credit Check URL. * @param form {@link FormJSON} * @return {@link String} */ private String getCreditCheckUrl(final FormJSON form) { String host = extractLabelAndValue(findValueByKey(form, "host").get().getValue()).getRight(); return host + "/sts/processinquiry.asp"; } /** * Get Request Cache. * @param form {@link FormJSON} * @return int */ private int getRequestCache(final FormJSON form) { int cache = 0; Optional<FormJSONField> op = findValueByKey(form, "requestcache"); if (op.isPresent()) { cache = NumberUtils.toInt(op.get().getValue(), 0); } return cache; } /** * Save Equifax Response. * @param cc {@link EquifaxCreditCheck} */ private void saveResponse(final EquifaxCreditCheck cc) { TransactionTemplate transactionTemplate = new TransactionTemplate(this.transactionManager); transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(final TransactionStatus status) { EquifaxServiceImpl.this.em .createNativeQuery("insert into equifax_credit_checks" + "(equifax_credit_check_id, url, request, response, " + "request_type,requester, inserted_date) " + "values (:id,:url,:req,:resp,:type,:requester,:date)") .setParameter("id", UUID.fromString(cc.getCreditcheckid())).setParameter("url", cc.getUrl()) .setParameter("req", cc.getRequest()).setParameter("resp", cc.getResponse()) .setParameter("type", cc.getRequesttype().name()) .setParameter("requester", cc.getRequester()).setParameter("date", new Date()) .executeUpdate(); } }); } @Override public EquifaxCreditCheck sendCreditCheck(final FormJSON form, final String request) { Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DAY_OF_MONTH, -1 * getRequestCache(form)); EquifaxCreditCheck resp = getCachedResponse(request, calendar.getTime()); if (resp == null) { EquifaxCreditCheckRequestType status = NEW; String url = getCreditCheckUrl(form); resp = new EquifaxCreditCheck(); resp.setRequest(request); resp.setUrl(url); try { String response = sendToEquifax(url, request); resp.setResponse(response); } catch (Exception e) { resp.setResponse(e.getMessage()); status = ERROR; } resp.setRequesttype(status); } else { resp.setRequesttype(CACHED); } Authentication auth = SecurityContextHolder.getContext().getAuthentication(); resp.setRequester(auth.getName()); resp.setRequest(request); resp.setInserteddate(new Date()); resp.setCreditcheckid(UUID.randomUUID().toString()); saveResponse(resp); return resp; } /** * Sends request to Equifax. * @param server {@link String} * @param send {@link String} * @return {@link String} * @throws IOException IOException */ public String sendToEquifax(final String server, final String send) throws IOException { String params = "InputSegments=" + URLEncoder.encode(send, "UTF-8") + "&cmdSubmit=Submit"; byte[] postData = params.getBytes(StandardCharsets.UTF_8); int postDataLength = postData.length; URL url = new URL(server); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setInstanceFollowRedirects(false); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty("charset", "utf-8"); conn.setRequestProperty("Content-Length", Integer.toString(postDataLength)); conn.setUseCaches(false); Reader in = null; DataOutputStream wr = null; try { wr = new DataOutputStream(conn.getOutputStream()); wr.write(postData); StringBuilder sb = new StringBuilder(); in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); for (int c = in.read(); c != -1; c = in.read()) { sb.append((char) c); } String receive = sb.toString(); return receive; } finally { if (in != null) { in.close(); } if (wr != null) { wr.close(); } } } /** * Transforms Database query to {@link EquifaxCreditCheck}. * @param vals Object[] * @return {@link EquifaxCreditCheck} */ private EquifaxCreditCheck transform(final Object[] vals) { int i = 0; EquifaxCreditCheck response = new EquifaxCreditCheck(); response.setRequest(vals[i++].toString()); response.setResponse(vals[i++].toString()); response.setRequesttype(EquifaxCreditCheckRequestType.valueOf(vals[i++].toString())); response.setUrl(vals[i++].toString()); response.setRequester(vals[i++].toString()); response.setInserteddate((Date) vals[i++]); return response; } /** * Transform {@link Query} to {@link List} of {@link EquifaxCreditCheck}. * @param query {@link Query} * @return {@link List} of {@link EquifaxCreditCheck} */ @SuppressWarnings("unchecked") private List<EquifaxCreditCheck> transform(final Query query) { List<Object[]> responses = query.getResultList(); List<EquifaxCreditCheck> results = new ArrayList<>(responses.size()); for (Object[] vals : responses) { EquifaxCreditCheck response = transform(vals); results.add(response); } return results; } }