Example usage for javax.persistence NonUniqueResultException getMessage

List of usage examples for javax.persistence NonUniqueResultException getMessage

Introduction

In this page you can find the example usage for javax.persistence NonUniqueResultException getMessage.

Prototype

public String getMessage() 

Source Link

Document

Returns the detail message string of this throwable.

Usage

From source file:org.rhq.enterprise.server.measurement.AvailabilityManagerBean.java

@SuppressWarnings("unchecked")
public boolean mergeAvailabilityReport(AvailabilityReport report) {
    int reportSize = report.getResourceAvailability().size();
    String agentName = report.getAgentName();
    StopWatch watch = new StopWatch();

    if (reportSize == 0) {
        log.error("Agent [" + agentName
                + "] sent an empty availability report.  This is a bug, please report it");
        return true; // even though this report is bogus, do not ask for an immediate full report to avoid unusual infinite recursion due to this error condition
    }//  w ww .  jav a 2  s  . com

    if (log.isDebugEnabled()) {
        if (reportSize > 1) {
            log.debug("Agent [" + agentName + "]: processing availability report of size: " + reportSize);
        }
    }

    // translate data into Availability objects for downstream processing
    List<Availability> availabilities = new ArrayList<Availability>(report.getResourceAvailability().size());
    for (AvailabilityReport.Datum datum : report.getResourceAvailability()) {
        availabilities.add(new Availability(new Resource(datum.getResourceId()), datum.getStartTime(),
                datum.getAvailabilityType()));
    }

    // We will alert only on the avails for enabled resources. Keep track of any that are disabled. 
    List<Availability> disabledAvailabilities = new ArrayList<Availability>();

    boolean askForFullReport = false;
    Integer agentToUpdate = agentManager.getAgentIdByName(agentName);

    // if this report is from an agent update the lastAvailreport time
    if (!report.isEnablementReport() && agentToUpdate != null) {
        // do this now, before we might clear() the entity manager
        availabilityManager.updateLastAvailabilityReport(agentToUpdate.intValue());
    }

    int numInserted = 0;

    // if this report is from an agent, and is a changes-only report, and the agent appears backfilled,
    // then we need to skip this report so as not to waste our time> Then, immediately request and process
    // a full report because, obviously, the agent is no longer down but the server thinks
    // it still is down - we need to know the availabilities for all the resources on that agent
    if (!report.isEnablementReport() && report.isChangesOnlyReport()
            && agentManager.isAgentBackfilled(agentToUpdate.intValue())) {
        askForFullReport = true;

    } else {
        Query q = entityManager.createNamedQuery(Availability.FIND_CURRENT_BY_RESOURCE);
        q.setFlushMode(FlushModeType.COMMIT);

        int count = 0;
        for (Availability reported : availabilities) {
            if ((++count % 100) == 0) {
                entityManager.flush();
                entityManager.clear();
            }

            // availability reports only tell us the current state at the start time; end time is ignored/must be null
            reported.setEndTime(null);

            try {
                q.setParameter("resourceId", reported.getResource().getId());
                Availability latest = (Availability) q.getSingleResult();
                AvailabilityType latestType = latest.getAvailabilityType();
                AvailabilityType reportedType = reported.getAvailabilityType();

                // If the current avail is DISABLED, and this report is not trying to re-enable the resource,
                // Then ignore the reported avail.
                if (AvailabilityType.DISABLED == latestType) {
                    if (!(report.isEnablementReport() && (AvailabilityType.UNKNOWN == reportedType))) {
                        disabledAvailabilities.add(reported);
                        continue;
                    }
                }

                if (reported.getStartTime() >= latest.getStartTime()) {
                    //log.info( "new avail (latest/reported)-->" + latest + "/" + reported );

                    // the new availability data is for a time after our last known state change
                    // we are runlength encoded, so only persist data if the availability changed                        
                    if (latest.getAvailabilityType() != reported.getAvailabilityType()) {
                        entityManager.persist(reported);
                        numInserted++;

                        latest.setEndTime(reported.getStartTime());
                        latest = entityManager.merge(latest);

                        updateResourceAvailability(reported);
                    }

                    // our last known state was unknown, ask for a full report to ensure we are in sync with agent
                    if (latest.getAvailabilityType() == AvailabilityType.UNKNOWN) {
                        askForFullReport = true;
                    }
                } else {
                    //log.info( "past avail (latest/reported)==>" + latest + "/" + reported );

                    // The new data is for a time in the past, probably an agent sending a report after
                    // a network outage has been corrected but after we have already backfilled.
                    // We need to insert it into our past timeline.
                    insertAvailability(reported);
                    numInserted++;

                    // this is an unusual report - ask the agent for a full report so as to ensure we are in sync with agent
                    askForFullReport = true;
                }
            } catch (NoResultException nre) {
                // This condition should never happen. An initial, unknown, Availability/ResourceAvailability
                // are created at resource persist time. But, just in case, handle it...
                log.warn("Resource [" + reported.getResource() + "] has no availability without an endtime ["
                        + nre.getMessage() + "] - will attempt to create one\n" + report.toString(false));

                entityManager.persist(reported);
                updateResourceAvailability(reported);
                numInserted++;

            } catch (NonUniqueResultException nure) {
                // This condition should never happen.  In my world of la-la land, I've done everything
                // correctly so this never happens.  But, due to the asynchronous nature of things,
                // I have to believe that this still might happen (albeit rarely).  If it does happen,
                // and we do nothing about it - bad things arise.  So, if we find that a resource
                // has 2 or more availabilities with endTime of null, we need to delete all but the
                // latest one (the one whose start time is the latest).  This should correct the
                // problem and allow us to continue processing availability reports for that resource
                log.warn("Resource [" + reported.getResource()
                        + "] has multiple availabilities without an endtime [" + nure.getMessage()
                        + "] - will attempt to remove the extra ones\n" + report.toString(false));

                q.setParameter("resourceId", reported.getResource().getId());
                List<Availability> latest = q.getResultList();

                // delete all but the last one (our query sorts in ASC start time order)
                int latestCount = latest.size();
                for (int i = 0; i < (latestCount - 1); i++) {
                    entityManager.remove(latest.get(i));
                }
                updateResourceAvailability(latest.get(latestCount - 1));

                // this is an unusual report - ask the agent for a full report so as to ensure we are in sync with agent
                askForFullReport = true;
            }
        }

        MeasurementMonitor.getMBean().incrementAvailabilityReports(report.isChangesOnlyReport());
        MeasurementMonitor.getMBean().incrementAvailabilitiesInserted(numInserted);
        MeasurementMonitor.getMBean().incrementAvailabilityInsertTime(watch.getElapsed());
        watch.reset();
    }

    // notify alert condition cache manager for all reported avails for for enabled resources
    availabilities.removeAll(disabledAvailabilities);
    notifyAlertConditionCacheManager("mergeAvailabilityReport",
            availabilities.toArray(new Availability[availabilities.size()]));

    if (!report.isEnablementReport()) {
        // a single report comes from a single agent - update the agent's last availability report timestamp
        if (agentToUpdate != null) {
            // don't bother asking for a full report if the one we are currently processing is already full
            if (askForFullReport && report.isChangesOnlyReport()) {
                log.debug("The server is unsure that it has up-to-date availabilities for agent [" + agentName
                        + "]; asking for a full report to be sent");
                return false;
            }
        } else {
            log.error("Could not figure out which agent sent availability report. "
                    + "This error is harmless and should stop appearing after a short while if the platform of the agent ["
                    + agentName + "] was recently removed. In any other case this is a bug." + report);
        }
    }

    return true; // everything is OK and things look to be in sync
}